DisplacementShader
VTKExamples/Cxx/Shaders/DisplacementShader
Code¶
DisplacementShader.cxx
#include <vtkSmartPointer.h> #include <vtkCamera.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkShaderProgram.h> #include <vtkActor.h> #include <vtkOpenGLPolyDataMapper.h> #include <vtkProperty.h> #include <vtkTransform.h> #include <vtkTransformPolyDataFilter.h> #include <vtkPolyDataNormals.h> #include <vtkTriangleFilter.h> #include <vtkCleanPolyData.h> #include <vtkNamedColors.h> #include <vtkRenderWindowInteractor.h> #include <vtksys/SystemTools.hxx> #include <vtkBYUReader.h> #include <vtkOBJReader.h> #include <vtkPLYReader.h> #include <vtkPolyDataReader.h> #include <vtkSTLReader.h> #include <vtkXMLPolyDataReader.h> #include <vtkSphereSource.h> #include <fstream> #include <sstream> namespace { vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName); } //---------------------------------------------------------------------------- int main(int argc, char *argv[]) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " PerlnNoise.glsl " << "[polydataFile] " << "[specksize(.05)] " << "[sizes(3)] " << "[basecolor{.7,.7,.7)] " << "[spattercolor(0.0,0.0,0.0)] " << std::endl; return EXIT_FAILURE; } vtkSmartPointer<vtkPolyData> polyData = ReadPolyData(argc > 2 ? argv[2] : ""); // Create a transform to rescale model double center[3]; polyData->GetCenter(center); double bounds[6]; polyData->GetBounds(bounds); double maxBound = std::max(std::max(bounds[1] - bounds[0], bounds[3] - bounds[2]), bounds[5] - bounds[4]); vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); vtkSmartPointer<vtkOpenGLPolyDataMapper> mapper = vtkSmartPointer<vtkOpenGLPolyDataMapper>::New(); renderer->SetBackground(colors->GetColor3d("SlateGray").GetData()); vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->SetSize(640, 480); renderWindow->AddRenderer(renderer); renderer->AddActor(actor); vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); interactor->SetRenderWindow(renderWindow); // Clean vtkSmartPointer<vtkCleanPolyData> clean = vtkSmartPointer<vtkCleanPolyData>::New(); clean->SetInputData(polyData); // Rescale polydata to [-1,1] vtkSmartPointer<vtkTransform> userTransform = vtkSmartPointer<vtkTransform>::New(); userTransform->Translate(-center[0], -center[1], -center[2]); userTransform->Scale(1.0/maxBound, 1.0/maxBound, 1.0/maxBound); vtkSmartPointer<vtkTransformPolyDataFilter> transform = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transform->SetTransform(userTransform); transform->SetInputConnection(clean->GetOutputPort()); vtkSmartPointer<vtkTriangleFilter> triangles = vtkSmartPointer<vtkTriangleFilter>::New(); triangles->SetInputConnection(transform->GetOutputPort()); vtkSmartPointer<vtkPolyDataNormals> norms = vtkSmartPointer<vtkPolyDataNormals>::New(); norms->SetInputConnection(triangles->GetOutputPort()); mapper->SetInputConnection(norms->GetOutputPort()); mapper->ScalarVisibilityOff(); actor->SetMapper(mapper); // Read noise functions std::ifstream shaderFile(argv[1]); std::ostringstream shaderCode; shaderCode << shaderFile.rdbuf(); // Define functions needed for displacement calculations shaderCode << "#define pnoise(x) ((noise(x) + 1.0) / 2.0);\n"; shaderCode << "float turbulence( vec3 p ) {\n" "float w = 100.0;\n" "float t = -.5;\n" " for (float f = 1.0 ; f <= 10.0 ; f += 1.0 ){\n" " float power = pow( 2.0, f );\n" " }\n" " return t;\n" "}\n" ; // Add the code to generate noise // These functions need to be defined outside of main. Use the System::Dec // to declare and implement mapper->AddShaderReplacement( vtkShader::Vertex, "//VTK::System::Dec", false, // before the standard replacements shaderCode.str(), false // only do it once ); mapper->AddShaderReplacement( vtkShader::Vertex, "VTK::PositionVC::Impl", true, // before the standard replacements "\n" " // get a turbulent 3d noise using the normal, normal to high freq\n" " float noisex = -1.0 * turbulence( .5 * normalMC );\n" " // get a 3d noise using the position, low frequency\n" " float p1 = 5.0 * noise (.05 * vertexMC);\n" " // compose both noises\n" " vec3 displacement = noise3(vec3(vertexMC.x,vertexMC.y,vertexMC.z));\n" "\n" " // move the position along the normal and transform it\n" " float factor = .05;\n" " vec3 newPosition = vec3(vertexMC.x,vertexMC.y,vertexMC.z) + factor * normalize(normalMC * displacement);\n" " vertexVCVSOutput = MCVCMatrix * vec4( newPosition, 1.0 );\n" " gl_Position = MCDCMatrix * vec4( newPosition, 1.0 );\n" , true // do it only once ); renderWindow->Render(); renderer->GetActiveCamera()->SetPosition(-.3, 0, .08); renderer->GetActiveCamera()->SetFocalPoint(0,0,0); renderer->GetActiveCamera()->SetViewUp(.26, 0.0, .96); renderer->ResetCamera(); renderer->GetActiveCamera()->Zoom(1.5); renderWindow->Render(); interactor->Start(); transform->GetOutput()->GetBounds(bounds); std::cout << "Range: " << " x " << bounds[1] - bounds[0] << " y " << bounds[3] - bounds[2] << " y " << bounds[5] - bounds[4] << std::endl; return EXIT_SUCCESS; } namespace { vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName) { vtkSmartPointer<vtkPolyData> polyData; std::string extension = vtksys::SystemTools::GetFilenameExtension(std::string(fileName)); if (extension == ".ply") { vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New(); reader->SetFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else if (extension == ".vtp") { vtkSmartPointer<vtkXMLPolyDataReader> reader = vtkSmartPointer<vtkXMLPolyDataReader>::New(); reader->SetFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else if (extension == ".obj") { vtkSmartPointer<vtkOBJReader> reader = vtkSmartPointer<vtkOBJReader>::New(); reader->SetFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else if (extension == ".stl") { vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New(); reader->SetFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else if (extension == ".vtk") { vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New(); reader->SetFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else if (extension == ".g") { vtkSmartPointer<vtkBYUReader> reader = vtkSmartPointer<vtkBYUReader>::New(); reader->SetGeometryFileName (fileName); reader->Update(); polyData = reader->GetOutput(); } else { vtkSmartPointer<vtkSphereSource> source = vtkSmartPointer<vtkSphereSource>::New(); source->SetPhiResolution(25); source->SetThetaResolution(25); source->Update(); polyData = source->GetOutput(); } return polyData; } }
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.3 FATAL_ERROR) project(DisplacementShader) find_package(VTK COMPONENTS vtkCommonColor vtkCommonCore vtkCommonTransforms vtkFiltersCore vtkFiltersGeneral vtkFiltersSources vtkIOGeometry vtkIOLegacy vtkIOPLY vtkIOXML vtkInteractionStyle vtkRenderingCore vtkRenderingFreeType vtkRenderingOpenGL2 QUIET) if (NOT VTK_FOUND) message("Skipping DisplacementShader: ${VTK_NOT_FOUND_MESSAGE}") return () endif() message (STATUS "VTK_VERSION: ${VTK_VERSION}") if (VTK_VERSION VERSION_LESS "8.90.0") # old system include(${VTK_USE_FILE}) add_executable(DisplacementShader MACOSX_BUNDLE DisplacementShader.cxx ) target_link_libraries(DisplacementShader PRIVATE ${VTK_LIBRARIES}) else () # include all components add_executable(DisplacementShader MACOSX_BUNDLE DisplacementShader.cxx ) target_link_libraries(DisplacementShader PRIVATE ${VTK_LIBRARIES}) # vtk_module_autoinit is needed vtk_module_autoinit( TARGETS DisplacementShader MODULES ${VTK_LIBRARIES} ) endif ()
Download and Build DisplacementShader¶
Click here to download DisplacementShader and its CMakeLists.txt file. Once the tarball DisplacementShader.tar has been downloaded and extracted,
cd DisplacementShader/build
If VTK is installed:
cmake ..
If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:
cmake -DVTK_DIR:PATH=/home/me/vtk_build ..
Build the project:
make
and run it:
./DisplacementShader
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.