Skip to content
Sammy Fatnassi edited this page Dec 30, 2023 · 15 revisions

Integration

Setup

  1. Add the downloaded sources files in .\Code\Client\ to your codebase and build process.
  2. (Optional) Generate the Visual Studio solutions.
    • Call .\GenerateProject.bat after downloading the sources from the NetImgui Git depot to generates Visual Studios solutions in .\_projects\.
    • Gives access to compiling the NetImgui Server Application and various Samples.

Integration

  1. Edit NetImgui_Config.h with the valid path to your Dear ImGui header files : imgui.h / imgui_internal.h.

    • Note : Your project should now compile
  2. On platforms without support for either Winsocks or POSIX or Unreal 4, the functions declared in NetImgui_Network.h needs to be implemented.

    • Allows data exchange between the NetImgui server and your application using socket connection.
    • 'NetImgui_NetworkWin32.cpp' can be used as a reference.

Note : Every memory allocations done in the NetImgui Client code uses the Dear ImGui allocator. Note : Users wanting to minimize changes to their project build process, #define NETIMGUI_IMPLEMENTATION can be added before #include NetImgui_Api.h to have this includes also pull the needed source files into the current source file. This should only happen in a single source file.

Changes to library user codebase

Very few changes are needed when displaying the same local Dear ImGui content on the remote NetImgui server.

Note 1: vs20XX_netImgui_Sample.sln offers good examples of NetImgui integration to a codebase

  • The 'SampleBasic' project in particular for small example.
  • The 'SampleNoBackend' project offers an even simpler integration example, without any local rendering supported.
1. [Init]
  • In your program startup, add a call to : NetImgui::Startup()
2. [Connect]
  • In your program startup (or potentially elsewhere), add a call to : NetImgui::ConnectToApp() or NetImgui::ConnectFromApp()

  • Note 1: Connection can be initiated from either the Server (ConnectFromApp) or Client (ConnectToApp), it is up to the integrater to decide which one they prefer.

  • Note 2: When initializing a connection, a new communication thread will be created using std::thread by default. A custom threading implementation can be used by providing a callback function to the connection function.

  • Note 3: The connection status can be determined with : NetImgui::IsConnected() and NetImgui::IsConnectionPending().

3. [Send Texture]
  • Textures used by your Dear ImGui menus need to be forwarded to the NetImgui server using NetImgui::SendDataTexture() (otherwise, content using it will be invisible).
  • The Font texture is automatically forwarded to the NetImgui Server if the Dear Imgui Font data hasn't been cleared (no call to ImFontAtlas::ClearTexData()). Otherwise, you will need to manually send it before releasing the Font.
  • Updating the textures can be done before or after establishing a connection to the NetImgui server.
4. [Step Draw]
For Dear ImGui version 1.81+
  • Nothing to do, NetImgui intercepts BeginFrame/Render automatically and works out of the box.
For Dear ImGui version 1.80- or wanting FrameSkip support

FrameSkip reduce cpu cost by only processing a new ImGui drawing when the Server is expecting a new frame. Without this, your application will draw the ImGui content and NetImgui will just drop the results.

Replace these calls in your codebase:

  • ImGui::NewFrame() with NetImgui::NewFrame()

  • ImGui::Render() / ImGui::EndFrame() with NetImGui::EndFrame() .

  • Note 1 (Important): When remote drawing, we don't need to update the Dear ImGui content every frame. If your UI drawing code can handle skipping frames, let NetImgui::NewFrame() know you want FramSkip support and it will returns false without calling ImGui::NewFrame(), when no refresh is expected. NetImgui::IsDrawing() can also be relied on to know about the status. This can reduce CPU usage of updating unused Dear ImGui content.

  • Note 2: NetImgui::IsDrawingRemote() can be used to customize the content when drawing Dear ImGui content.

  • Note 3: It is possible to have content displayed simultaneously on the remote netImgui server and locally, with distinct content on each output. The Sample SampleDualUI has more information.

5. [Step Shutdown]

In your program shutdown, add a call to : NetImgui::Shutdown()

Reducing bandwidth

  • The bandwidth amount between the Client / Server mostly depends on the complexity of the content
  • It is not tied to the screen resolution.
    • NetImgui sends the drawing data (vertex, index, drawcalls), not the rendering result.
  • To control the bandwidth, the refresh rate can be adjusted on the Server Settings.
  • By default, a data compression method is also enabled.
    • Greatly reduce the bandwidth between Client/Server at a negligible cost on the Client
    • Using Delta Compression. The draw data usually vary little from previous frame. Sending only the changed bytes produce great results at low overhead
    • Highly dynamic UI content lower improvements
    • A new sample (SampleCompression) demonstrate the use of data compression and its metrics
      • At 30 Fps, data rate send from client goes from ~ 3400 KB/s to ~ 22 KB/s (~ 160x improvement !)
      • Since it depends on static content, moving around a Window reduce the benefits
  • This data compression can be set on the Server Settings
  • It is also possible to ignore the server setting and let the Client chose its preference.
    • Use NetImgui::GetCompressionMode / NetImgui::SetCompressionMode to manage compression on the client.
  • The sample 'SampleCompression' exist to see the effect of changing these settings.

FAQ

  • A connection seems to be sucessfully established, but nothing is drawed on the Server :
  • A missing Font texture is the most likely cause.
  • Either avoid releasing the Dear Imgui's Font data by not calling ImGui::GetIO().Fonts->ClearTexData().
  • Or manually send the texture before releasing the Font data :
unsigned char* pixels(nullptr);
int width(0), height(0);
ImGui::GetIO().Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
NetImgui::SendDataTexture(ImGui::GetIO().Fonts->TexID, pixels, static_cast<uint16_t>(width), static_cast<uint16_t>(height), NetImgui::eTexFormat::kTexFmtA8);