Repository: napari/napari

Issue:
[main] 3D rendering of labels has wrong colors (mostly label 1, brown)
### 🐛 Bug Report

3D rendering of labels is broken, label colors are not displayed properly:
<img width="1198" alt="image" src="https://github.com/napari/napari/assets/76622105/490bd989-68bd-4642-9828-cb930fa9626d">

Git bisect points to ca2d186e1e908a19c5a34c932215ebc86afed88d

0.4.18 and 0.4.19rc3 are both fine.

### 💡 Steps to Reproduce

Script:
```
import napari
from skimage import data
from scipy import ndimage as ndi

blobs = data.binary_blobs(length=128, volume_fraction=0.1, n_dim=3)
labeled = ndi.label(blobs)[0]
viewer = napari.Viewer()
viewer.add_labels(labeled, name='blob ID')
viewer.dims.ndisplay = 3
```
Or use the super new `Balls 3D` sample!

### 💡 Expected Behavior

The 3D labels should still use the proper label colors.

### 🌎 Environment

napari: 0.5.0a2.dev520+gec90e5c3c
Platform: macOS-13.3.1-arm64-arm-64bit
System: MacOS 13.3.1
Python: 3.11.7 | packaged by conda-forge | (main, Dec 15 2023, 08:41:36) [Clang 16.0.6 ]
Qt: 6.6.0
PyQt6: 
NumPy: 1.26.3
SciPy: 1.11.4
Dask: 2023.12.1
VisPy: 0.14.1
magicgui: 0.8.1
superqt: 0.6.1
in-n-out: 0.1.9
app-model: 0.2.4
npe2: 0.7.3

OpenGL:
  - GL version:  2.1 Metal - 83.1
  - MAX_TEXTURE_SIZE: 16384

Screens:
  - screen 1: resolution 1680x1050, scale 2.0

Settings path:
  - /Users/piotrsobolewski/Library/Application Support/napari/napari-dev_a1eb8b76ba95fa16ad06e26097b46b8455dfbf0b/settings.yaml
Plugins:
ERROR:npe2.manifest.schema:napari.manifest -> 'napari_animation' could not be imported: The name field in the manifest ('napari-animation') must match the package name ('napari_animation')
  - napari: 0.5.0a2.dev495+gd507dd64e (81 contributions)
  - napari-console: 0.0.9 (0 contributions)
  - napari-svg: 0.1.10 (2 contributions)

### 💡 Additional Context

_No response_


Discussion:
Looks like an issue with interpolation and it does look like interpolation was removed from labels during the refactor, as far as I can tell.
Gah, thanks for the report @psobolewskiPhD! I had noticed but it's one of those things where I was like "hmmm probably something weird with my install env, will investigate later". 😅 Hopefully not too hard to fix. Great to have discovered it before the next rc.

Resolving patch:
diff --git a/napari/_qt/qt_viewer.py b/napari/_qt/qt_viewer.py
--- a/napari/_qt/qt_viewer.py
+++ b/napari/_qt/qt_viewer.py
@@ -21,6 +21,7 @@
 )
 from weakref import WeakSet, ref
 
+import numpy as np
 from qtpy.QtCore import QCoreApplication, QObject, Qt, QUrl
 from qtpy.QtGui import QGuiApplication
 from qtpy.QtWidgets import QFileDialog, QSplitter, QVBoxLayout, QWidget
@@ -784,7 +785,7 @@ def _screenshot(self, flash=True):
             add_flash_animation(self._welcome_widget)
         return img
 
-    def screenshot(self, path=None, flash=True):
+    def screenshot(self, path=None, flash=True) -> np.ndarray:
         """Take currently displayed screen and convert to an image array.
 
         Parameters
diff --git a/napari/_vispy/layers/labels.py b/napari/_vispy/layers/labels.py
--- a/napari/_vispy/layers/labels.py
+++ b/napari/_vispy/layers/labels.py
@@ -337,6 +337,7 @@ def _setup_nodes(self, texture_format):
             ),
             clim=[0, 2**23 - 1],
             texture_format=texture_format,
+            interpolation='nearest',
         )
 
     def get_node(self, ndisplay: int, dtype=None) -> Node:


Test patch:
diff --git a/napari/_qt/_tests/test_qt_viewer.py b/napari/_qt/_tests/test_qt_viewer.py
--- a/napari/_qt/_tests/test_qt_viewer.py
+++ b/napari/_qt/_tests/test_qt_viewer.py
@@ -911,6 +911,22 @@ def test_background_color(qtbot, qt_viewer: QtViewer, dtype):
         )
 
 
+def test_rendering_interpolation(qtbot, qt_viewer):
+    data = np.zeros((20, 20, 20), dtype=np.uint8)
+    data[1:-1, 1:-1, 1:-1] = 5
+    layer = qt_viewer.viewer.add_labels(
+        data, opacity=1, rendering="translucent"
+    )
+    layer.selected_label = 5
+    qt_viewer.viewer.dims.ndisplay = 3
+    QApplication.processEvents()
+    canvas_screenshot = qt_viewer.screenshot(flash=False)
+    shape = np.array(canvas_screenshot.shape[:2])
+    pixel = canvas_screenshot[tuple((shape * 0.5).astype(int))]
+    color = layer.colormap.map(5)[0] * 255
+    npt.assert_array_equal(pixel, color)
+
+
 def test_shortcut_passing(make_napari_viewer):
     viewer = make_napari_viewer(ndisplay=3)
     layer = viewer.add_labels(