A shadow plus bold, slightly smaller font looks good to me. A screen-space halo would be even better but I donāt think thatās available in VTK.
OHIF defaults to a yellow which is more readable sometimes but not always.
They use a convention I do like though, which is that the markup is green while itās being actively defined (e.g. when only one point of a line has been placed) the then it gets itās final color when completed.
In anatomical drawings/labelling, it is common to pair these lines with a color that is much darker in contrast (e.g., white/black, yellow/blue etc), so that part of the line remains visible regardless both in areas of high/low contrast. On option like this would be great actually!
Yes, thatās what the drop shadow does, but our default markup color is too dark. Iāve never really cared for that red color actually. It carries over from the days when you needed to use bland colors so they could be recorded to VHS tape (clearly no longer a requirement).
Yeah, sorry, that was a pretty useless observation. Iāll try to get something more concreteā¦ I just have a few scenes where drop shadows donāt seem to show. Iāll work on steps to reproduce.
I meant the line/curve itself as well, not just the markups label. Even in your example above, part of the the yellow line is hard to see.
Also in the stable version, the two unselected and active color is either identical or too close to differentiate (I really canāt tell). I set them to be different, and then hit Save as Defaults, but this is not retained after Slicer is restarted. Is this a bug or a color defaults are not meant to be saved ? In comparison glyph/text size changes are saved and retained correctly.
Currently, only ābasicā display properties can be saved as default. This made sense when there were not too many display properties, but now there are dozens, and it is very hard to select a meaningful subset. So, Iāll change the implementation to save/restore all display properties.
I agree that we would need high-contrast outline for lines and markers as well. One option is to use additional rendering passes, such as Gaussian or glow pass, but that would require some work (adding two additional rendering layers and improve image quality of these rendering passes, because glow pass is optimized for adding bright glow and not dark shadow and the outline is not continuous; Gaussian step is hardcoded to 5 pixels, which is not sufficient as a border).
newRenderer=False
gaussian=False
if newRenderer:
iren = vtk.vtkRenderWindowInteractor()
renWin = vtk.vtkRenderWindow()
renWin.SetMultiSamples(0)
iren.SetRenderWindow(renWin)
renderer = vtk.vtkRenderer()
rendererOutline = vtk.vtkRenderer()
rendererOutline.SetLayer(1)
renWin.SetNumberOfLayers(2)
renWin.AddRenderer(rendererOutline)
renWin.AddRenderer(renderer)
else:
layoutManager = slicer.app.layoutManager()
view = layoutManager.sliceWidget('Red').sliceView()
renderWindow = view.renderWindow()
renderers = renderWindow.GetRenderers()
renderer = renderers.GetItemAsObject(0)
renderWindow.SetNumberOfLayers(renderWindow.GetNumberOfLayers()+2)
renderer = vtk.vtkRenderer()
rendererOutline = vtk.vtkRenderer()
if gaussian:
renderer.SetLayer(renderWindow.GetNumberOfLayers()-1)
rendererOutline.SetLayer(renderWindow.GetNumberOfLayers()-2)
else:
renderer.SetLayer(renderWindow.GetNumberOfLayers()-2)
rendererOutline.SetLayer(renderWindow.GetNumberOfLayers()-1)
renderWindow.AddRenderer(renderer)
renderWindow.AddRenderer(rendererOutline)
basicPasses = vtk.vtkRenderStepsPass()
if gaussian:
glowPass = vtk.vtkGaussianBlurPass()
else:
glowPass = vtk.vtkOutlineGlowPass()
glowPass.SetOutlineIntensity(1.0)
glowPass.SetDelegatePass(basicPasses)
# Apply the render pass to the highlight renderer
rendererOutline.SetPass(glowPass)
outlineColor = [1.0, 1.0, 1.0]
# Create mapper and actor for the main renderer
coneSource = vtk.vtkConeSource()
coneMapperMain = vtk.vtkPolyDataMapper()
coneMapperMain.SetInputConnection(coneSource.GetOutputPort())
coneActorMain = vtk.vtkActor()
coneActorMain.SetMapper(coneMapperMain)
renderer.AddActor(coneActorMain)
# Create mapper and actor for the outline
coneMapperOutline = vtk.vtkPolyDataMapper()
coneMapperOutline.SetInputConnection(coneSource.GetOutputPort())
coneActorOutline = vtk.vtkActor()
coneActorOutline.SetMapper(coneMapperOutline)
coneActorOutline.GetProperty().SetColor(outlineColor)
coneActorOutline.GetProperty().LightingOff()
rendererOutline.AddActor(coneActorOutline)
fontSize=20
textActor = vtk.vtkTextActor()
textActor.SetDisplayPosition(100, 100);
textActor.SetVisibility(True)
textActor.GetTextProperty().SetFontSize(fontSize)
textActor.GetTextProperty().SetColor(0,0,0)
textActor.SetInput("This is a test")
renderer.AddActor(textActor)
textActorOutline = vtk.vtkTextActor()
textActorOutline.SetDisplayPosition(100, 100);
textActorOutline.SetVisibility(True)
textActorOutline.GetTextProperty().SetColor(outlineColor)
textActorOutline.GetTextProperty().SetFontSize(fontSize)
textActorOutline.SetInput("This is a test")
rendererOutline.AddActor(textActorOutline)
if newRenderer:
renWin.SetSize(400, 400)
renderer.ResetCamera()
camera = renderer.GetActiveCamera()
camera.Azimuth(-40.0)
camera.Elevation(20.0)
renderer.ResetCamera()
rendererOutline.SetActiveCamera(camera)
renWin.Render()
iren.Start()
Another option is to render thicker dark line in the same renderer behind the normal line:
With enabling FXAA anti-aliasing (to make the line edges smoother):
Code snippet to enable FXAA anti-aliasing
view = slicer.app.layoutManager().sliceWidget('Red').sliceView()
#view = slicer.app.layoutManager().threeDWidget(0).threeDView()
renderWindow = view.renderWindow()
renderers = renderWindow.GetRenderers()
for renderer in renderers:
renderer.UseFXAAOn()
Probably we should expose FXAA anti-aliasing option to users, too. It performs smart smoothing in the rendered image (only smoothing at sharp edges), which may impact anything in the rendering layer, but if we render markups in a separate layer (which is easy to do in slice views) then we can ensure that only markups edges are smoothed.
Iāve submitted a pull request to enable bold and shadow by default for markup labels, a potential fix for the issue when shadow cannot be enabled, and saving/restoring all markups display properties as default:
Iāve added an issue to track the remaining enhancement ideas:
I think I was able to find out what was happening with shadows not showing up but not why. In a scene where I didnāt see any drop shadows, the scene MRML had the textProperty setting for the MarkupsFiducialDisplay node set with text-shadow:0px 0px 2px rgba(0,0,0,1.0);. All I had to do was manually change it to text-shadow:2px 2px 2px rgba(0,0,0,1.0); and drop shadows showed up.