Files
t5de-renderer/renderer/scene.hpp
T
dhkatzandClaude Opus 5.5 299cd8c312 Fix particle sizes, and add tools for comparing renderers
Particles: Direct3D 9's size limit evidently isn't the documented 64 pixels; unclamped (up to 2048) they match the client's renderer. A compare view shows the left half's scene over the right half, both renderers side by side; %TEMP%\t5de-renderer-view.txt switches views and %TEMP%\t5de-renderer-shaders\fixed_function.hlsl replaces the shaders while the client runs. The renderer process runs from a copy, so the program can be replaced meanwhile. The adapter recognizes only the textures and buffers it made (others reach the client renderer unchanged) and logs the others and render targets.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 06:43:34 -07:00

130 lines
5.0 KiB
C++

#pragma once
// Carries out the command stream (include/t5de/protocol/commands.hpp) with Diligent, reproducing IMVU's Direct3D 9
// look (shaders/fixed_function.hlsl): the client's textures and buffers by id, its state as it sets it, a pipeline
// for each combination of states it draws with.
#include <cstddef>
#include <cstdint>
#include <span>
#include <string>
#include <unordered_map>
#include "EngineFactoryD3D11.h"
#include "RefCntAutoPtr.hpp"
#include "t5de/protocol/commands.hpp"
namespace t5de {
class Scene {
public:
Scene(Diligent::IRenderDevice* device, Diligent::IDeviceContext* context, Diligent::ISwapChain* swapChain);
// Carries out one frame's commands. offsetX is where the window starts within the client's 3D view; without draw,
// only the frame's changes are made (textures, buffers, state). True if the frame was drawn into the window (to
// present).
bool execute(std::span<const std::byte> commands, int offsetX, bool draw);
// Replaces the shaders' source (the built-in one by default): for trying changes while the client runs.
void setShaderSource(std::string source);
// When the adapter sent the last frame carried out (QueryPerformanceCounter).
[[nodiscard]] std::uint64_t lastSentAt() const { return lastSentAt_; }
private:
struct Texture {
Diligent::RefCntAutoPtr<Diligent::ITexture> texture;
std::uint32_t width = 0;
std::uint32_t height = 0;
std::uint32_t flags = 0;
};
struct Buffer {
Diligent::RefCntAutoPtr<Diligent::IBuffer> buffer;
protocol::BufferKind kind = protocol::BufferKind::Vertex;
std::uint32_t elementSize = 0;
std::uint32_t count = 0;
};
struct Pipeline {
Diligent::RefCntAutoPtr<Diligent::IPipelineState> state;
Diligent::RefCntAutoPtr<Diligent::IShaderResourceBinding> bindings;
Diligent::IShaderResourceVariable* texture0 = nullptr;
Diligent::IShaderResourceVariable* texture1 = nullptr;
};
struct Shaders {
Diligent::RefCntAutoPtr<Diligent::IShader> vertex;
Diligent::RefCntAutoPtr<Diligent::IShader> pixel;
};
// Mirrors the shader's constant buffer.
struct Constants {
float world[16];
float view[16];
float projection[16];
float texTransform0[8];
float texTransform1[8];
float ambient[4];
float lightColor[8][4];
float lightVector[8][4];
float fogColor[4];
float fog[4];
float flags[4];
float viewport[4];
};
// What a draw needs from the state, as set by the client.
struct State {
bool depthTest = true;
bool depthWrite = true;
bool blending = false;
std::uint32_t blendMode = 1;
bool culling = true;
bool normalInverting = false;
std::uint32_t texture0 = 0;
std::uint32_t texture1 = 0;
};
void createTexture(const protocol::Command& command);
void updateTexture(const protocol::Command& command);
void createBuffer(const protocol::Command& command);
void updateBuffer(const protocol::Command& command);
void setProjection(const protocol::SetProjection& projection);
void setState(const protocol::SetState& state);
void drawTriangles(const protocol::DrawTriangles& draw);
void drawArrays(const protocol::Command& command);
void drawPointSprites(const protocol::Command& command);
// Draws indexCount indices from index, with vertex streams (positions required, the others may be null).
void draw(Diligent::IBuffer* indices, std::uint32_t indexCount, Diligent::IBuffer* positions,
Diligent::IBuffer* normals, Diligent::IBuffer* texCoords, Diligent::IBuffer* colors);
// The pipeline for the current state, with these vertex streams and textures, for triangles or particles.
Pipeline* pipeline(std::uint32_t streams, std::uint32_t textures, bool sprites);
const Shaders& shaders(std::uint32_t streams, std::uint32_t textures, bool sprites);
// Picks the pipeline for the current state and sets it up for a draw: constants, textures. Null if it can't.
Pipeline* prepare(std::uint32_t streams, bool sprites);
Diligent::ITextureView* textureView(std::uint32_t id);
Diligent::RefCntAutoPtr<Diligent::IRenderDevice> device_;
Diligent::RefCntAutoPtr<Diligent::IDeviceContext> context_;
Diligent::RefCntAutoPtr<Diligent::ISwapChain> swapChain_;
Diligent::RefCntAutoPtr<Diligent::IBuffer> constantBuffer_;
Diligent::RefCntAutoPtr<Diligent::ISampler> samplers_[4]; // by wrap u (1) and wrap v (2)
std::unordered_map<std::uint32_t, Texture> textures_;
std::unordered_map<std::uint32_t, Buffer> buffers_;
std::unordered_map<std::uint32_t, Shaders> shaders_;
std::unordered_map<std::uint32_t, Pipeline> pipelines_;
std::string shaderSource_;
Constants constants_{};
State state_;
bool onscreen_ = false; // in a frame drawn into the window
bool draw_ = true;
std::uint64_t lastSentAt_ = 0;
int spritesLogged_ = 0;
int offsetX_ = 0;
};
} // namespace t5de