ctroesch
(Clément)
June 26, 2025, 10:04am
1
I there,
I just moved from VTK 9.3.0 to VTK 9.5.0 and I experiment rendering glitches when displaying a scene with vtkSSAOPass on MacOS:
I’m on an MacOS 15.4.1 (Sequoia) and using Xcode 16.3 (Apple clang version 17.0.0).
Here is a simple example to reproduce the issue:
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCubeSource.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkOpenGLRenderer.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderStepsPass.h>
#include <vtkSSAOPass.h>
#include <vtkOpaquePass.h>
#include <vtkProperty.h>
int main() {
// Cube source
vtkNew<vtkCubeSource> cube;
cube->SetXLength(1.0);
cube->SetYLength(1.0);
cube->SetZLength(1.0);
cube->Update();
// Mapper and Actor
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(cube->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(1.0, 0.5, 0.3);
actor->GetProperty()->SetInterpolationToPBR();
actor->GetProperty()->SetMetallic(0.3);
actor->GetProperty()->SetRoughness(0.5);
// Renderer
vtkNew<vtkOpenGLRenderer> renderer;
renderer->SetBackground(0.1, 0.1, 0.1);
renderer->AddActor(actor);
// SSAO pass setup
vtkNew<vtkSSAOPass> ssaoPass;
vtkNew<vtkOpaquePass> opaquePass;
ssaoPass->SetDelegatePass(opaquePass); // SSAO wraps opaque geometry
vtkNew<vtkRenderStepsPass> stepsPass;
stepsPass->SetOpaquePass(ssaoPass); // Inject SSAO into render pipeline
renderer->SetPass(stepsPass); // Use composed render pass
// Render window and interactor
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(800, 600);
vtkNew<vtkRenderWindowInteractor> interactor;
interactor->SetRenderWindow(renderWindow);
// Camera setup
renderer->ResetCamera();
renderer->GetActiveCamera()->Azimuth(30);
renderer->GetActiveCamera()->Elevation(30);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
cmake_minimum_required(VERSION 3.16)
project(vtk-test-app VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE Debug)
# Note: Update path to VTK
set(CMAKE_PREFIX_PATH "../vtk/install/lib/cmake")
find_package(VTK REQUIRED COMPONENTS
CommonCore
FiltersSources
InteractionStyle
RenderingCore
RenderingOpenGL2
RenderingFreeType
RenderingVolumeOpenGL2
RenderingSceneGraph
)
if (NOT VTK_FOUND)
message(FATAL_ERROR "Unable to find the VTK build folder.")
endif()
set(CMAKE_AUTOUIC OFF)
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp)
add_executable(vtk-test-app ${SRC_FILES})
target_link_libraries(vtk-test-app PRIVATE ${VTK_LIBRARIES})
# vtk_module_autoinit is needed
vtk_module_autoinit(
TARGETS vtk-test-app
MODULES ${VTK_LIBRARIES}
)
I had no issue running the example with VTK 9.3.0.
Is this a bug or did I miss something following the update ?
Thanks a lot,
Clément
1 Like
lgivord
(Lucas Givord (Kitware))
June 26, 2025, 1:08pm
2
It’s definitively a bug, @LucasGandel does that ring a bell ?
1 Like
Your render passes setup looks weird to me. The steps pass should be the delegate of the ssao pass. Here is how the VTK test initializes the render passes:
vtkNew<vtkRenderStepsPass> basicPasses;
vtkNew<vtkSSAOPass> ssao;
ssao->SetRadius(0.05);
ssao->SetKernelSize(128);
ssao->SetDelegatePass(basicPasses);
vtkOpenGLRenderer* glrenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
glrenderer->SetPass(ssao);
Is the result the same if you use this code?
ctroesch
(Clément)
June 27, 2025, 8:52am
4
Thanks for the replies.
You are right, your configuration works to display the SSAO, however when I add a depth peeling pass, the SSAO doesn’t work anymore I get the following warning:
vtkOpenGLState.cxx:623 WARN| Attempt to set draw buffers from a Framebuffer Object that is not bound.
I guess there is something wrong in the way I set up the rendering passes, here is my updated code:
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCubeSource.h>
#include <vtkDepthPeelingPass.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkOBJReader.h>
#include <vtkOpaquePass.h>
#include <vtkOpenGLRenderer.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderStepsPass.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSSAOPass.h>
#include <array>
#include <string>
vtkSmartPointer<vtkActor> read(const std::string& filename, std::array<double, 4> color)
{
// Read the OBJ file
vtkNew<vtkOBJReader> reader;
reader->SetFileName(filename.c_str());
reader->Update();
// Mapper and Actor
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(reader->GetOutputPort());
const auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(color[0], color[1], color[2]);
actor->GetProperty()->SetOpacity(color[3]);
actor->GetProperty()->SetInterpolationToPBR();
actor->GetProperty()->SetMetallic(0);
actor->GetProperty()->SetRoughness(0.5);
return actor;
}
int main() {
// Renderer
vtkNew<vtkOpenGLRenderer> renderer;
renderer->SetBackground(0.1, 0.1, 0.1);
// Load meshes
renderer->AddActor(read("Bronchus.obj", { 1, 0.9, 0.9, 1 }));
renderer->AddActor(read("Pulmonary_Artery.obj", { 1, 0.1, 0.1, 1 }));
renderer->AddActor(read("Pulmonary_Vein.obj", { 0.2, 0.4, 1, 1 }));
renderer->AddActor(read("Left_Lung.obj", { 1, 0.8, 0.9, 0.4 }));
// Create steps pass
vtkNew<vtkRenderStepsPass> stepsPass;
// Depth Peeling pass
vtkNew<vtkDepthPeelingPass> depthPeelingPass;
depthPeelingPass->SetMaximumNumberOfPeels(8);
depthPeelingPass->SetOcclusionRatio(0);
depthPeelingPass->SetTranslucentPass(stepsPass->GetTranslucentPass());
stepsPass->SetTranslucentPass(depthPeelingPass);
// SSAO pass setup
vtkNew<vtkSSAOPass> ssaoPass;
ssaoPass->SetDelegatePass(stepsPass);
ssaoPass->SetRadius(20);
ssaoPass->SetKernelSize(256);
// Use SSAO pass as render pass
renderer->SetPass(ssaoPass);
// Render window and interactor
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(800, 600);
vtkNew<vtkRenderWindowInteractor> interactor;
interactor->SetRenderWindow(renderWindow);
// Camera setup
renderer->ResetCamera();
renderer->GetActiveCamera()->Elevation(-90);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
And this is the result with and without depth peeling:
Any clue on what is wrong with my configuration ?
Thanks a lot,
Clément
ctroesch
(Clément)
June 27, 2025, 9:39am
5
Alright, I managed to make it work by using a custom vtkRenderPassCollection
and a dedicated SSAO camera pass.
Someone had a similar issue in python:
The odd color behavior is related to an internal color buffer that you are not supposed to see.
Note that you will be able to enable SSAO without render passes in VTK 9.1.
In the mean time, you can try something equivalent to F3D render passes :
lightsP = vtk.vtkLightsPass()
opaqueP = vtk.vtkOpaquePass()
translucentP = vtk.vtkTranslucentPass()
volumeP = vtk.vtkVolumetricPass()
collection = vtk.vtkRenderPassCollection()
collection.AddItem(lightsP)
# opaque passes
…
For anyone interested this is my final setup to make SSAO & Depth Peeling work together:
vtkNew<vtkOpaquePass> opaque;
vtkNew<vtkCameraPass> ssaoCameraPass;
ssaoCameraPass->SetDelegatePass(opaque);
vtkNew<vtkSSAOPass> ssaoPass;
ssaoPass->SetDelegatePass(ssaoCameraPass); // SSAO applies to opaque geometry
ssaoPass->SetRadius(20);
ssaoPass->SetKernelSize(256);
// Depth peeling for translucent geometry
vtkNew<vtkDepthPeelingPass> peelingPass;
peelingPass->SetMaximumNumberOfPeels(16);
peelingPass->SetOcclusionRatio(0.01);
vtkNew<vtkTranslucentPass> translucentPass;
peelingPass->SetTranslucentPass(translucentPass);
vtkNew<vtkLightsPass> lights;
// Compose the sequence
vtkNew<vtkRenderPassCollection> passes;
passes->AddItem(lights);
passes->AddItem(ssaoPass); // SSAO for opaque geometry
passes->AddItem(peelingPass); // Depth peeling for translucent
vtkNew<vtkSequencePass> sequence;
sequence->SetPasses(passes);
// Wrap it into a camera pass
vtkNew<vtkCameraPass> cameraPass;
cameraPass->SetDelegatePass(sequence);
// Set the final pass
renderer->SetPass(cameraPass);
Thanks for the help,
Clément
1 Like
Nice, thanks for sharing!
1 Like