Draw the client's scene in the renderer process

The adapter records everything the client draws (state, transforms, lights, fog, textures and buffers) as a command stream, sent in chunks through the shared memory channel, while IMVU's Direct3D renderer still draws the whole view. The renderer process draws it with Diligent, with shaders reproducing IMVU's Direct3D 9 fixed-function setup, over the right half of the 3D view to compare. It skips to the newest frame when it falls behind, and logs its errors and frame times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 05:52:15 -07:00
1 parent 5c35c8b63a
commit 42fc55cb91
23 files changed
+2121 -472

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
#pragma once
// Generated by CMake from renderer/shaders/@T5DE_SHADER_FILE@: the shader source, compiled at run time by Diligent.
inline constexpr const char* @T5DE_SHADER_NAME@ = R"hlsl(@T5DE_SHADER_SOURCE@)hlsl";
+117
View File
@@ -0,0 +1,117 @@
// IMVU's Direct3D 9 fixed-function look, as its renderer sets it up (docs/interface.md):
// - per-vertex (Gouraud) lighting, with the vertex color as diffuse and ambient material (white without one): the
// environment's ambient light, plus each light's color times max(0, N.L); no specular or emissive light;
// - textures: none (the lit color), one (times the lit color), or two (the second blended over the first by its
// alpha, then times the lit color), both on the vertex's texture coordinates with their own transforms;
// - an alpha test passing pixels whose alpha is greater than the reference, then linear fog by view depth.
//
// Compiled for each combination of the vertex streams present (HAS_NORMALS, HAS_TEX_COORDS, HAS_COLORS) and the
// number of textures (TEXTURES).
cbuffer Constants
{
row_major float4x4 g_World;
row_major float4x4 g_View;
row_major float4x4 g_Projection;
float4 g_TexTransform0[2]; // u' = dot((u, v, 1), [0].xyz), v' = dot((u, v, 1), [1].xyz)
float4 g_TexTransform1[2];
float4 g_Ambient; // rgb
float4 g_LightColor[8]; // rgb, a: enabled
float4 g_LightVector[8]; // xyz: position, or direction toward the light; w: 1 if directional
float4 g_FogColor; // rgb
float4 g_Fog; // x: start, y: end, z: on
float4 g_Flags; // x: lighting on, y: alpha test on, z: alpha reference (0-255)
};
struct VSInput
{
float3 Position : ATTRIB0;
#if HAS_NORMALS
float3 Normal : ATTRIB1;
#endif
#if HAS_TEX_COORDS
float2 TexCoord : ATTRIB2;
#endif
#if HAS_COLORS
float4 Color : ATTRIB3; // bytes B, G, R, A
#endif
};
struct PSInput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TexCoord0 : TEXCOORD0;
float2 TexCoord1 : TEXCOORD1;
float Depth : TEXCOORD2;
};
void vs_main(in VSInput input, out PSInput output)
{
float4 world = mul(float4(input.Position, 1.0), g_World);
float4 view = mul(world, g_View);
output.Position = mul(view, g_Projection);
output.Depth = abs(view.z);
float4 material = float4(1.0, 1.0, 1.0, 1.0);
#if HAS_COLORS
material = input.Color.zyxw;
#endif
float4 color = material;
if (g_Flags.x > 0.5)
{
float3 normal = float3(0.0, 0.0, 0.0);
#if HAS_NORMALS
normal = normalize(mul(input.Normal, (float3x3)g_World));
#endif
float3 lit = g_Ambient.rgb * material.rgb;
for (int i = 0; i < 8; ++i)
{
if (g_LightColor[i].a > 0.5)
{
float3 toLight = g_LightVector[i].w > 0.5 ? g_LightVector[i].xyz : g_LightVector[i].xyz - world.xyz;
lit += g_LightColor[i].rgb * material.rgb * max(0.0, dot(normal, normalize(toLight)));
}
}
color = float4(saturate(lit), material.a);
}
output.Color = color;
float3 uv = float3(0.0, 0.0, 1.0);
#if HAS_TEX_COORDS
uv.xy = input.TexCoord;
#endif
output.TexCoord0 = float2(dot(uv, g_TexTransform0[0].xyz), dot(uv, g_TexTransform0[1].xyz));
output.TexCoord1 = float2(dot(uv, g_TexTransform1[0].xyz), dot(uv, g_TexTransform1[1].xyz));
}
#if TEXTURES >= 1
Texture2D g_Texture0;
SamplerState g_Texture0_sampler;
#endif
#if TEXTURES >= 2
Texture2D g_Texture1;
SamplerState g_Texture1_sampler;
#endif
float4 ps_main(in PSInput input) : SV_Target
{
float4 color = input.Color;
#if TEXTURES == 1
color *= g_Texture0.Sample(g_Texture0_sampler, input.TexCoord0);
#elif TEXTURES == 2
float4 first = g_Texture0.Sample(g_Texture0_sampler, input.TexCoord0);
float4 second = g_Texture1.Sample(g_Texture1_sampler, input.TexCoord1);
color *= lerp(first, second, second.a);
#endif
if (g_Flags.y > 0.5 && !(color.a * 255.0 > g_Flags.z))
{
discard;
}
if (g_Fog.z > 0.5)
{
float visible = saturate((g_Fog.y - input.Depth) / max(g_Fog.y - g_Fog.x, 1e-6));
color.rgb = lerp(g_FogColor.rgb, color.rgb, visible);
}
return color;
}