Map projections' depth like the client's renderer

IMVU's projections give depth from -1 to 1; its Direct3D renderer maps it to 0 to 1, and now so does ours. Without that, the nearer half of the depth range was clipped, the whole 2D overlay (name tags, the frame rate, the room's title) with it. The adapter also draws drawTrianglesFromMemory without indices, and sums up what the client draws in its log.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 07:01:47 -07:00
1 parent 299cd8c312
commit 3cdda4c7ed
6 files changed
+78 -43

No files matched your search

+7 -36
View File
@@ -1,13 +1,9 @@
#include "scene.hpp"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstring>
#include <string>
#include "fixed_function_hlsl.hpp"
#include "log.hpp"
namespace t5de {
@@ -227,6 +223,13 @@ bool Scene::execute(std::span<const std::byte> commands, int offsetX, bool draw)
void Scene::setProjection(const protocol::SetProjection& projection)
{
std::memcpy(constants_.projection, projection.m, sizeof(constants_.projection));
// The client's projections give depth from -1 to 1, as OpenGL does; IMVU's Direct3D renderer maps it to 0 to 1
// (z' = z / 2 + w / 2) before setting them, and so do we. (It also shifts them half a pixel, which Direct3D 9
// needs and Direct3D 11 doesn't.)
for (int row = 0; row < 4; ++row) {
float* m = constants_.projection + row * 4;
m[2] = 0.5f * m[2] + 0.5f * m[3];
}
constants_.viewport[0] = static_cast<float>(projection.width);
constants_.viewport[1] = static_cast<float>(projection.height);
if (!onscreen_) {
@@ -545,38 +548,6 @@ void Scene::drawPointSprites(const protocol::Command& command)
if (!buffer || prepare(0, true) == nullptr) {
return;
}
if (spritesLogged_ < 5) {
++spritesLogged_;
const Texture* texture = textures_.contains(state_.texture0) ? &textures_[state_.texture0] : nullptr;
log::info("particles: {}, texture {} {}x{} flags {}, blending {} mode {}, depth test {} write {}, alpha test {} "
"reference {}, lighting {}, fog {}, ambient ({:.2f} {:.2f} {:.2f}), texture transform [{} {} {} {} {} {}]",
sprites->count, state_.texture0, texture ? texture->width : 0, texture ? texture->height : 0,
texture ? texture->flags : 0, state_.blending, state_.blendMode, state_.depthTest, state_.depthWrite,
constants_.flags[1], constants_.flags[2], constants_.flags[0], constants_.fog[2], constants_.ambient[0],
constants_.ambient[1], constants_.ambient[2], constants_.texTransform0[0], constants_.texTransform0[1],
constants_.texTransform0[2], constants_.texTransform0[4], constants_.texTransform0[5],
constants_.texTransform0[6]);
// The first sprite: where it is, seen from the camera, and how big it's drawn.
float point[4] = {0, 0, 0, 1};
std::uint32_t color = 0;
std::memcpy(point, payload.data(), 12);
std::memcpy(&color, payload.data() + 12, 4);
const auto transform = [](const float (&p)[4], const float (&m)[16]) {
std::array<float, 4> out{};
for (int column = 0; column < 4; ++column) {
out[column] = p[0] * m[column] + p[1] * m[4 + column] + p[2] * m[8 + column] + p[3] * m[12 + column];
}
return out;
};
const auto world = transform(point, constants_.world);
const float worldPoint[4] = {world[0], world[1], world[2], world[3]};
const auto view = transform(worldPoint, constants_.view);
const float distance = std::sqrt(view[0] * view[0] + view[1] * view[1] + view[2] * view[2]);
log::info(" first sprite at ({:.2f} {:.2f} {:.2f}), color {:08x}, from the camera ({:.2f} {:.2f} {:.2f}): "
"distance {:.2f}, {:.1f} pixels across (viewport height {})",
point[0], point[1], point[2], color, view[0], view[1], view[2], distance,
std::clamp(constants_.viewport[1] / std::max(distance, 1e-4f), 1.0f, 2048.0f), constants_.viewport[1]);
}
IBuffer* buffers[] = {buffer};
context_->SetVertexBuffers(0, 1, buffers, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
SET_VERTEX_BUFFERS_FLAG_RESET);
-1
View File
@@ -122,7 +122,6 @@ private:
bool onscreen_ = false; // in a frame drawn into the window
bool draw_ = true;
std::uint64_t lastSentAt_ = 0;
int spritesLogged_ = 0;
int offsetX_ = 0;
};