Backends: WebGPU: added SetSamplerLinear/Nearest draw callbacks. (#9378)
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 0b89abe..fe01dcf 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -8,7 +8,7 @@
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 //  [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
 // Missing features or Issues:
-//  [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest, DrawCallback_SetSamplerCustom callbacks.
+//  [ ] Renderer: Missing support for DrawCallback_SetSamplerCustom.
 
 // Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
 
@@ -22,7 +22,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
-//  2026-XX-XX: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported).
+//  2026-XX-XX: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest.
 //  2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
 //  2026-03-09: Removed support for Emscripten < 4.0.10. (#9281)
 //  2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898)
@@ -86,11 +86,13 @@
 
 struct RenderResources
 {
-    WGPUSampler         SamplerLinear = nullptr;        // Sampler for textures
-    WGPUBuffer          Uniforms = nullptr;             // Shader uniforms
-    WGPUBindGroup       CommonBindGroup = nullptr;      // Resources bind-group to bind the common resources to pipeline
-    ImGuiStorage        ImageBindGroups;                // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
-    WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
+    WGPUSampler         SamplerLinear = nullptr;            // Bilinear sampler
+    WGPUSampler         SamplerNearest = nullptr;           // Nearest/point sampler
+    WGPUBuffer          Uniforms = nullptr;                 // Shader uniforms
+    WGPUBindGroup       CommonBindGroupLinear = nullptr;    // Common bind-group bound to group 0 (uniforms + SamplerLinear)
+    WGPUBindGroup       CommonBindGroupNearest = nullptr;   // Common bind-group bound to group 0 (uniforms + SamplerNearest)
+    ImGuiStorage        ImageBindGroups;                    // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
+    WGPUBindGroupLayout ImageBindGroupLayout = nullptr;     // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
 };
 
 struct FrameResources
@@ -117,6 +119,7 @@
     WGPUTextureFormat       renderTargetFormat = WGPUTextureFormat_Undefined;
     WGPUTextureFormat       depthStencilFormat = WGPUTextureFormat_Undefined;
     WGPURenderPipeline      pipelineState = nullptr;
+    ImGui_ImplWGPU_RenderState* RenderState = nullptr;  // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
 
     RenderResources         renderResources;
     FrameResources*         pFrameResources = nullptr;
@@ -300,8 +303,10 @@
 static void SafeRelease(RenderResources& res)
 {
     SafeRelease(res.SamplerLinear);
+    SafeRelease(res.SamplerNearest);
     SafeRelease(res.Uniforms);
-    SafeRelease(res.CommonBindGroup);
+    SafeRelease(res.CommonBindGroupLinear);
+    SafeRelease(res.CommonBindGroupNearest);
     SafeRelease(res.ImageBindGroupLayout);
 };
 
@@ -423,7 +428,7 @@
     wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert));
     wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx));
     wgpuRenderPassEncoderSetPipeline(ctx, bd->pipelineState);
-    wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroup, 0, nullptr);
+    wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr);
 
     // Setup blend factor
     WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
@@ -431,7 +436,9 @@
 }
 
 // Draw callbacks
-static void ImGui_ImplWGPU_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
+static void ImGui_ImplWGPU_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*)   {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
+static void ImGui_ImplWGPU_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*)   { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr); }
+static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*)  { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); wgpuRenderPassEncoderSetBindGroup(bd->RenderState->RenderPassEncoder, 0, bd->renderResources.CommonBindGroupNearest, 0, nullptr); }
 
 // Render function
 void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
@@ -528,7 +535,7 @@
     ImGui_ImplWGPU_RenderState render_state;
     render_state.Device = bd->wgpuDevice;
     render_state.RenderPassEncoder = pass_encoder;
-    platform_io.Renderer_RenderState = &render_state;
+    platform_io.Renderer_RenderState = bd->RenderState = &render_state;
 
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -591,7 +598,7 @@
     }
     image_bind_groups.Data.resize(0);
 
-    platform_io.Renderer_RenderState = nullptr;
+    platform_io.Renderer_RenderState = bd->RenderState = nullptr;
 }
 
 static void ImGui_ImplWGPU_DestroyTexture(ImTextureData* tex)
@@ -819,19 +826,23 @@
 
     ImGui_ImplWGPU_CreateUniformBuffer();
 
-    // Create sampler
+    // Create samplers (Linear/Nearest)
     // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
     WGPUSamplerDescriptor sampler_desc = {};
-    sampler_desc.minFilter = WGPUFilterMode_Linear;
-    sampler_desc.magFilter = WGPUFilterMode_Linear;
-    sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
     sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
     sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
     sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge;
     sampler_desc.maxAnisotropy = 1;
+    sampler_desc.minFilter = WGPUFilterMode_Linear;
+    sampler_desc.magFilter = WGPUFilterMode_Linear;
+    sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
     bd->renderResources.SamplerLinear = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
+    sampler_desc.minFilter = WGPUFilterMode_Nearest;
+    sampler_desc.magFilter = WGPUFilterMode_Nearest;
+    sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Nearest;
+    bd->renderResources.SamplerNearest = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
 
-    // Create resource bind group
+    // Create resource bind groups (one per sampler, otherwise identical)
     WGPUBindGroupEntry common_bg_entries[] =
     {
         { nullptr, 0, bd->renderResources.Uniforms, 0, MEMALIGN(sizeof(Uniforms), 16), 0, 0 },
@@ -841,7 +852,9 @@
     common_bg_descriptor.layout = bg_layouts[0];
     common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
     common_bg_descriptor.entries = common_bg_entries;
-    bd->renderResources.CommonBindGroup = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
+    bd->renderResources.CommonBindGroupLinear = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
+    common_bg_entries[1].sampler = bd->renderResources.SamplerNearest;
+    bd->renderResources.CommonBindGroupNearest = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor);
     bd->renderResources.ImageBindGroupLayout = bg_layouts[1];
 
     SafeRelease(vertex_shader_desc.module);
@@ -895,6 +908,8 @@
 
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
     platform_io.DrawCallback_ResetRenderState = ImGui_ImplWGPU_DrawCallback_ResetRenderState;
+    platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplWGPU_DrawCallback_SetSamplerLinear;
+    platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplWGPU_DrawCallback_SetSamplerNearest;
 
     bd->initInfo = *init_info;
     bd->wgpuDevice = init_info->Device;
@@ -904,11 +919,7 @@
     bd->numFramesInFlight = init_info->NumFramesInFlight;
     bd->frameIndex = UINT_MAX;
 
-    bd->renderResources.SamplerLinear = nullptr;
-    bd->renderResources.Uniforms = nullptr;
-    bd->renderResources.CommonBindGroup = nullptr;
     bd->renderResources.ImageBindGroups.Data.reserve(100);
-    bd->renderResources.ImageBindGroupLayout = nullptr;
 
     // Create buffers with a default size (they will later be grown as needed)
     bd->pFrameResources = new FrameResources[bd->numFramesInFlight];
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index 2e4ea92..e1bbf9d 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -20,7 +20,7 @@
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 //  [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
 // Missing features or Issues:
-//  [ ] Renderer: Missing support for DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest, DrawCallback_SetSamplerCustom callbacks.
+//  [ ] Renderer: Missing support for DrawCallback_SetSamplerCustom.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 3df4120..658d895 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -145,7 +145,7 @@
     - SDLRenderer2: Reset     n/a               n/a                n/a
     - SDLRenderer3: Reset     SetSamplerLinear  SetSamplerNearest  n/a
     - Vulkan:       Reset     SetSamplerLinear  SetSamplerNearest  SetSamplerCustom
-    - WebGPU:       Reset     *missing*         *missing*          *missing*
+    - WebGPU:       Reset     SetSamplerLinear  SetSamplerNearest  *missing*
     (Vulkan backend by @yaz0r, others by @ocornut)
   - GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
     functions for legacy GLFW 3.2. (#9003)