MarbleShaderDemo
Repository source: MarbleShaderDemo
Description¶
Makes solid marble texture with strong veins. The "veincolor" parameter controls the color of the veins. The background color is given by the surface's DiffuseColor.
Explore the parameter space with the vtkSliderWidget.
Parameters¶
- veinfreq - controls the lowest frequency of the color veins e.g. 10
- veinlevels - how many "levels" of vein tendrils it has e.g. 2
- warpfreq - lowest frequency of the turbulent warping in the marble e.g. 10
- _ warping_ - controls how much turbulent warping there will be e.g. 0.5
- veincolor - the color of the veins e.g. white: 1 1 1
- sharpness - controls how sharp or fuzzy the veins are (higher = sharper) e.g. 8
Cite
This shader is inspired by Larry Gritz's veined marble shader.
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
MarbleShaderDemo.cxx
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkNamedColors.h>
#include <vtkOpenGLPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkShaderProgram.h>
#include <vtkSmartPointer.h>
#include <vtkVersion.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkTriangleFilter.h>
#include <vtkTriangleMeshPointNormals.h>
#include <vtkBYUReader.h>
#include <vtkOBJReader.h>
#include <vtkPLYReader.h>
#include <vtkPolyDataReader.h>
#include <vtkSTLReader.h>
#include <vtkSphereSource.h>
#include <vtkXMLPolyDataReader.h>
#include <vtksys/SystemTools.hxx>
#include <vtkSliderRepresentation2D.h>
#include <vtkSliderWidget.h>
#if VTK_VERSION_NUMBER >= 89000000000ULL
#define USE_SHADER_PROPERTIES 1
#include <vtkShaderProperty.h>
#endif
#include <chrono>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#define DELAY 200
namespace {
// -----------------------------------------------------------------------
// Update uniform variables in the shader for each render. We do this with a
// callback for the UpdateShaderEvent
class ShaderCallback : public vtkCommand
{
public:
static ShaderCallback* New()
{
return new ShaderCallback;
}
vtkRenderer* Renderer;
float veincolor[3];
float veinfreq;
float veinlevels;
float warpfreq;
float warping;
float sharpness;
void Execute(vtkObject*, unsigned long, void* calldata) override
{
vtkShaderProgram* program = reinterpret_cast<vtkShaderProgram*>(calldata);
if (program)
{
program->SetUniform3f("veincolor", veincolor);
program->SetUniformf("veinfreq", veinfreq);
program->SetUniformi("veinlevels", veinlevels);
program->SetUniformf("warpfreq", warpfreq);
program->SetUniformf("warping", warping);
program->SetUniformf("sharpness", sharpness);
std::cout << "------------" << std::endl;
Print(std::cout);
}
}
void Print(std::ostream& os)
{
os << "veincolor: " << veincolor[0] << ", " << veincolor[1] << ", "
<< veincolor[2] << std::endl;
os << "veinfreq: " << veinfreq << std::endl;
os << "veinlevels: " << veinlevels << std::endl;
os << "warpfreq: " << warpfreq << std::endl;
os << "warping: " << warping << std::endl;
os << "sharpness: " << sharpness << std::endl;
}
ShaderCallback()
{
this->Renderer = nullptr;
this->veincolor[0] = this->veincolor[1] = this->veincolor[2] = 1.0;
this->veinfreq = 10.0;
this->veinlevels = 2;
this->warpfreq = 1.0;
this->warping = .5;
this->sharpness = 8.0;
}
};
// These callbacks do the actual work.
// Callbacks for the interactions
class SliderCallbackVeinFreq : public vtkCommand
{
public:
static SliderCallbackVeinFreq* New()
{
return new SliderCallbackVeinFreq;
}
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
float value = static_cast<vtkSliderRepresentation2D*>(
sliderWidget->GetRepresentation())
->GetValue();
this->Shader->veinfreq = value;
std::this_thread::sleep_for(std::chrono::milliseconds(DELAY));
}
SliderCallbackVeinFreq() : Shader(0)
{
}
ShaderCallback* Shader;
};
// These callbacks do the actual work.
// Callbacks for the interactions
class SliderCallbackVeinLevels : public vtkCommand
{
public:
static SliderCallbackVeinLevels* New()
{
return new SliderCallbackVeinLevels;
}
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
int value = static_cast<vtkSliderRepresentation2D*>(
sliderWidget->GetRepresentation())
->GetValue();
static_cast<vtkSliderRepresentation2D*>(sliderWidget->GetRepresentation())
->SetValue(value);
this->Shader->veinlevels = value;
std::this_thread::sleep_for(std::chrono::milliseconds(DELAY));
}
SliderCallbackVeinLevels() : Shader(0)
{
}
ShaderCallback* Shader;
};
class SliderCallbackWarpFreq : public vtkCommand
{
public:
static SliderCallbackWarpFreq* New()
{
return new SliderCallbackWarpFreq;
}
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
float value = static_cast<vtkSliderRepresentation2D*>(
sliderWidget->GetRepresentation())
->GetValue();
this->Shader->warpfreq = value;
std::this_thread::sleep_for(std::chrono::milliseconds(DELAY));
}
SliderCallbackWarpFreq() : Shader(0)
{
}
ShaderCallback* Shader;
};
class SliderCallbackWarping : public vtkCommand
{
public:
static SliderCallbackWarping* New()
{
return new SliderCallbackWarping;
}
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller);
float value = static_cast<vtkSliderRepresentation2D*>(
sliderWidget->GetRepresentation())
->GetValue();
this->Shader->warping = value;
std::this_thread::sleep_for(std::chrono::milliseconds(DELAY));
}
SliderCallbackWarping() : Shader(0)
{
}
ShaderCallback* Shader;
};
} // namespace
namespace {
vtkSmartPointer<vtkPolyData> ReadPolyData(const char* fileName);
}
//----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: " << argv[0] << " PerlnNoise.glsl "
<< "[polydataFile] " << "[veincolor(1,1,1)] " << "[veinfreq(10)] "
<< "[veinlevels(2)] " << "[warpfreq(1)] " << "[warping(.5)] "
<< "[sharpness(8)]" << std::endl;
return EXIT_FAILURE;
}
auto polyData = ReadPolyData(argc > 2 ? argv[2] : "");
std::ifstream shaderFile(argv[1]);
std::ostringstream shaderCode;
shaderCode << shaderFile.rdbuf();
// 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]);
auto colors = vtkSmartPointer<vtkNamedColors>::New();
auto actor = vtkSmartPointer<vtkActor>::New();
auto renderer = vtkSmartPointer<vtkRenderer>::New();
auto mapper = vtkSmartPointer<vtkOpenGLPolyDataMapper>::New();
renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(640, 480);
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
interactor->SetInteractorStyle(style);
// Rescale polydata to [-1,1]
auto userTransform = vtkSmartPointer<vtkTransform>::New();
userTransform->Translate(-center[0], -center[1], -center[2]);
userTransform->Scale(1.0 / maxBound, 1.0 / maxBound, 1.0 / maxBound);
auto transform = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transform->SetTransform(userTransform);
transform->SetInputData(polyData);
auto triangles = vtkSmartPointer<vtkTriangleFilter>::New();
triangles->SetInputConnection(transform->GetOutputPort());
auto norms = vtkSmartPointer<vtkTriangleMeshPointNormals>::New();
norms->SetInputConnection(triangles->GetOutputPort());
mapper->SetInputConnection(norms->GetOutputPort());
mapper->ScalarVisibilityOff();
actor->SetMapper(mapper);
actor->GetProperty()->SetDiffuse(1.0);
actor->GetProperty()->SetDiffuseColor(colors->GetColor3d("wheat").GetData());
actor->GetProperty()->SetSpecular(.5);
actor->GetProperty()->SetSpecularPower(50);
// Modify the vertex shader to pass the position of the vertex
#if USE_SHADER_PROPERTIES
vtkShaderProperty* sp = actor->GetShaderProperty();
sp->AddVertexShaderReplacement(
"//VTK::Normal::Dec", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Dec\n" // we still want the default
" out vec4 myVertexMC;\n",
false // only do it once
);
#else
mapper->AddShaderReplacement(
vtkShader::Vertex,
"//VTK::Normal::Dec", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Dec\n" // we still want the default
" out vec4 myVertexMC;\n",
false // only do it once
);
#endif
#if USE_SHADER_PROPERTIES
sp->AddVertexShaderReplacement(
"//VTK::Normal::Impl", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Impl\n" // we still want the default
" myVertexMC = vertexMC;\n",
false // only do it once
);
#else
mapper->AddShaderReplacement(
vtkShader::Vertex,
"//VTK::Normal::Impl", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Impl\n" // we still want the default
" myVertexMC = vertexMC;\n",
false // only do it once
);
#endif
// Add the code to generate noise
// These functions need to be defined outside of main. Use the System::Dec
// to declare and implement
#if USE_SHADER_PROPERTIES
sp->AddFragmentShaderReplacement("//VTK::System::Dec",
false, // before the standard replacements
shaderCode.str(),
false // only do it once
);
#else
mapper->AddShaderReplacement(vtkShader::Fragment, // in the fragment shader
"//VTK::System::Dec",
false, // before the standard replacements
shaderCode.str(),
false // only do it once
);
#endif
// Define varying and uniforms for the fragment shader here
#if USE_SHADER_PROPERTIES
sp->AddFragmentShaderReplacement(
"//VTK::Normal::Dec", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Dec\n" // we still want the default
" varying vec4 myVertexMC;\n"
" uniform vec3 veincolor = vec3(1.0, 1.0, 1.0);\n"
" uniform float veinfreq = 10.0;\n"
" uniform int veinlevels = 2;\n"
" uniform float warpfreq = 1;\n"
" uniform float warping = .5;\n"
" uniform float sharpness = 8.0;\n",
false // only do it once
);
#else
mapper->AddShaderReplacement(
vtkShader::Fragment, // in the fragment shader
"//VTK::Normal::Dec", // replace the normal block
true, // before the standard replacements
"//VTK::Normal::Dec\n" // we still want the default
" varying vec4 myVertexMC;\n"
" uniform vec3 veincolor = vec3(1.0, 1.0, 1.0);\n"
" uniform float veinfreq = 10.0;\n"
" uniform int veinlevels = 2;\n"
" uniform float warpfreq = 1;\n"
" uniform float warping = .5;\n"
" uniform float sharpness = 8.0;\n",
false // only do it once
);
#endif
#if USE_SHADER_PROPERTIES
sp->AddFragmentShaderReplacement(
"//VTK::Light::Impl", // replace the light block
false, // after the standard replacements
"//VTK::Light::Impl\n" // we still want the default calc
"\n"
"#define pnoise(x) ((noise(x) + 1.0) / 2.0)\n"
"#define snoise(x) (2.0 * pnoise(x) - 1.0)\n"
" vec3 Ct;\n"
" int i;\n"
" float turb, freq;\n"
" float turbsum;\n"
" /* perturb the lookup */\n"
" freq = 1.0;\n"
" vec4 offset = vec4(0.0,0.0,0.0,0.0);\n"
" vec4 noisyPoint;\n"
" vec4 myLocalVertexMC = myVertexMC;\n"
"\n"
" for (i = 0; i < 6; i += 1) {\n"
" noisyPoint[0] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[1] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[2] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[3] = 1.0;\n"
" offset += 2.0 * warping * (noisyPoint - 0.5) / freq;\n"
" freq *= 2.0;\n"
" }\n"
" myLocalVertexMC.x += offset.x;\n"
" myLocalVertexMC.y += offset.y;\n"
" myLocalVertexMC.z += offset.z;\n"
"\n"
" /* Now calculate the veining function for the lookup area */\n"
" turbsum = 0.0; freq = 1.0;\n"
" myLocalVertexMC *= veinfreq;\n"
" for (i = 0; i < veinlevels; i += 1) {\n"
" turb = abs (snoise (myLocalVertexMC));\n"
" turb = pow (smoothstep (0.8, 1.0, 1.0 - turb), sharpness) / "
"freq;\n"
" turbsum += (1.0-turbsum) * turb;\n"
" freq *= 1.5;\n"
" myLocalVertexMC *= 1.5;\n"
" }\n"
"\n"
" Ct = mix (diffuseColor, veincolor, turbsum);\n"
"\n"
" fragOutput0.rgb = opacity * (ambientColor + Ct + specular);\n"
" fragOutput0.a = opacity;\n",
false // only do it once
);
#else
mapper->AddShaderReplacement(
vtkShader::Fragment, // in the fragment shader
"//VTK::Light::Impl", // replace the light block
false, // after the standard replacements
"//VTK::Light::Impl\n" // we still want the default calc
"\n"
"#define pnoise(x) ((noise(x) + 1.0) / 2.0)\n"
"#define snoise(x) (2.0 * pnoise(x) - 1.0)\n"
" vec3 Ct;\n"
" int i;\n"
" float turb, freq;\n"
" float turbsum;\n"
" /* perturb the lookup */\n"
" freq = 1.0;\n"
" vec4 offset = vec4(0.0,0.0,0.0,0.0);\n"
" vec4 noisyPoint;\n"
" vec4 myLocalVertexMC = myVertexMC;\n"
"\n"
" for (i = 0; i < 6; i += 1) {\n"
" noisyPoint[0] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[1] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[2] = snoise(warpfreq * freq * myLocalVertexMC);\n"
" noisyPoint[3] = 1.0;\n"
" offset += 2.0 * warping * (noisyPoint - 0.5) / freq;\n"
" freq *= 2.0;\n"
" }\n"
" myLocalVertexMC.x += offset.x;\n"
" myLocalVertexMC.y += offset.y;\n"
" myLocalVertexMC.z += offset.z;\n"
"\n"
" /* Now calculate the veining function for the lookup area */\n"
" turbsum = 0.0; freq = 1.0;\n"
" myLocalVertexMC *= veinfreq;\n"
" for (i = 0; i < veinlevels; i += 1) {\n"
" turb = abs (snoise (myLocalVertexMC));\n"
" turb = pow (smoothstep (0.8, 1.0, 1.0 - turb), sharpness) / "
"freq;\n"
" turbsum += (1.0-turbsum) * turb;\n"
" freq *= 1.5;\n"
" myLocalVertexMC *= 1.5;\n"
" }\n"
"\n"
" Ct = mix (diffuseColor, veincolor, turbsum);\n"
"\n"
" fragOutput0.rgb = opacity * (ambientColor + Ct + specular);\n"
" fragOutput0.a = opacity;\n",
false // only do it once
);
#endif
auto myCallback = vtkSmartPointer<ShaderCallback>::New();
myCallback->Renderer = renderer;
std::cout << "Input: " << (argc > 2 ? argv[2] : "Generated Sphere")
<< std::endl;
myCallback->Print(std::cout);
mapper->AddObserver(vtkCommand::UpdateShaderEvent, myCallback);
// Setup a slider widget for each varying parameter
double tubeWidth(.015);
double sliderLength(.008);
double titleHeight(.02);
double labelHeight(.02);
auto sliderRepVeinFreq = vtkSmartPointer<vtkSliderRepresentation2D>::New();
sliderRepVeinFreq->SetMinimumValue(1.0);
sliderRepVeinFreq->SetMaximumValue(15.0);
sliderRepVeinFreq->SetValue(7.5);
sliderRepVeinFreq->SetTitleText("Vein Frequency");
sliderRepVeinFreq->GetPoint1Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepVeinFreq->GetPoint1Coordinate()->SetValue(.1, .1);
sliderRepVeinFreq->GetPoint2Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepVeinFreq->GetPoint2Coordinate()->SetValue(.9, .1);
sliderRepVeinFreq->SetTubeWidth(tubeWidth);
sliderRepVeinFreq->SetSliderLength(sliderLength);
sliderRepVeinFreq->SetTitleHeight(titleHeight);
sliderRepVeinFreq->SetLabelHeight(labelHeight);
auto sliderWidgetVeinFreq = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidgetVeinFreq->SetInteractor(interactor);
sliderWidgetVeinFreq->SetRepresentation(sliderRepVeinFreq);
sliderWidgetVeinFreq->SetAnimationModeToAnimate();
sliderWidgetVeinFreq->SetNumberOfAnimationSteps(10);
sliderWidgetVeinFreq->EnabledOn();
auto callbackVeinFreq = vtkSmartPointer<SliderCallbackVeinFreq>::New();
callbackVeinFreq->Shader = myCallback;
sliderWidgetVeinFreq->AddObserver(vtkCommand::InteractionEvent,
callbackVeinFreq);
auto sliderRepVeinLevels = vtkSmartPointer<vtkSliderRepresentation2D>::New();
sliderRepVeinLevels->SetMinimumValue(1);
sliderRepVeinLevels->SetMaximumValue(5);
sliderRepVeinLevels->SetValue(3);
sliderRepVeinLevels->SetTitleText("Vein Levels");
sliderRepVeinLevels->GetPoint1Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepVeinLevels->GetPoint1Coordinate()->SetValue(.1, .9);
sliderRepVeinLevels->GetPoint2Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepVeinLevels->GetPoint2Coordinate()->SetValue(.9, .9);
sliderRepVeinLevels->SetTubeWidth(tubeWidth);
sliderRepVeinLevels->SetSliderLength(sliderLength);
sliderRepVeinLevels->SetTitleHeight(titleHeight);
sliderRepVeinLevels->SetLabelHeight(labelHeight);
auto sliderWidgetVeinLevels = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidgetVeinLevels->SetInteractor(interactor);
sliderWidgetVeinLevels->SetRepresentation(sliderRepVeinLevels);
sliderWidgetVeinLevels->SetAnimationModeToAnimate();
sliderWidgetVeinLevels->SetNumberOfAnimationSteps(10);
sliderWidgetVeinLevels->EnabledOn();
auto callbackVeinLevels = vtkSmartPointer<SliderCallbackVeinLevels>::New();
callbackVeinLevels->Shader = myCallback;
myCallback->veincolor[0] = colors->GetColor3d("Green").GetData()[0];
myCallback->veincolor[1] = colors->GetColor3d("Green").GetData()[1];
myCallback->veincolor[2] = colors->GetColor3d("Green").GetData()[2];
sliderWidgetVeinLevels->AddObserver(vtkCommand::InteractionEvent,
callbackVeinLevels);
auto sliderRepWarpFreq = vtkSmartPointer<vtkSliderRepresentation2D>::New();
sliderRepWarpFreq->SetMinimumValue(1.0);
sliderRepWarpFreq->SetMaximumValue(2.0);
sliderRepWarpFreq->SetValue(1.5);
sliderRepWarpFreq->SetTitleText("Warp Frequency");
sliderRepWarpFreq->GetPoint1Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepWarpFreq->GetPoint1Coordinate()->SetValue(.1, .1);
sliderRepWarpFreq->GetPoint2Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepWarpFreq->GetPoint2Coordinate()->SetValue(.1, .9);
sliderRepWarpFreq->SetTubeWidth(tubeWidth);
sliderRepWarpFreq->SetSliderLength(sliderLength);
sliderRepWarpFreq->SetTitleHeight(titleHeight);
sliderRepWarpFreq->SetLabelHeight(labelHeight);
auto sliderWidgetWarpFreq = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidgetWarpFreq->SetInteractor(interactor);
sliderWidgetWarpFreq->SetRepresentation(sliderRepWarpFreq);
sliderWidgetWarpFreq->SetAnimationModeToAnimate();
sliderWidgetWarpFreq->SetNumberOfAnimationSteps(10);
sliderWidgetWarpFreq->EnabledOn();
auto callbackWarpFreq = vtkSmartPointer<SliderCallbackWarpFreq>::New();
callbackWarpFreq->Shader = myCallback;
sliderWidgetWarpFreq->AddObserver(vtkCommand::InteractionEvent,
callbackWarpFreq);
auto sliderRepWarping = vtkSmartPointer<vtkSliderRepresentation2D>::New();
sliderRepWarping->SetMinimumValue(0.0);
sliderRepWarping->SetMaximumValue(1.0);
sliderRepWarping->SetValue(.5);
sliderRepWarping->SetTitleText("Warping");
sliderRepWarping->GetPoint1Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepWarping->GetPoint1Coordinate()->SetValue(.9, .1);
sliderRepWarping->GetPoint2Coordinate()
->SetCoordinateSystemToNormalizedDisplay();
sliderRepWarping->GetPoint2Coordinate()->SetValue(.9, .9);
sliderRepWarping->SetTubeWidth(tubeWidth);
sliderRepWarping->SetSliderLength(sliderLength);
sliderRepWarping->SetTitleHeight(titleHeight);
sliderRepWarping->SetLabelHeight(labelHeight);
auto sliderWidgetWarping = vtkSmartPointer<vtkSliderWidget>::New();
sliderWidgetWarping->SetInteractor(interactor);
sliderWidgetWarping->SetRepresentation(sliderRepWarping);
sliderWidgetWarping->SetAnimationModeToAnimate();
sliderWidgetWarping->SetNumberOfAnimationSteps(10);
sliderWidgetWarping->EnabledOn();
auto callbackWarping = vtkSmartPointer<SliderCallbackWarping>::New();
callbackWarping->Shader = myCallback;
sliderWidgetWarping->AddObserver(vtkCommand::InteractionEvent,
callbackWarping);
renderWindow->Render();
renderer->ResetCamera();
renderer->GetActiveCamera()->Zoom(1.5);
renderWindow->Render();
renderWindow->SetWindowName("MarbleShaderDemo");
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")
{
auto reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".vtp")
{
auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".obj")
{
auto reader = vtkSmartPointer<vtkOBJReader>::New();
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".stl")
{
auto reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".vtk")
{
auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".g")
{
auto reader = vtkSmartPointer<vtkBYUReader>::New();
reader->SetGeometryFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else
{
auto source = vtkSmartPointer<vtkSphereSource>::New();
source->SetPhiResolution(25);
source->SetThetaResolution(25);
source->Update();
polyData = source->GetOutput();
}
return polyData;
}
} // namespace
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(MarbleShaderDemo)
find_package(VTK COMPONENTS
CommonColor
CommonCore
CommonTransforms
FiltersCore
FiltersGeneral
FiltersSources
IOGeometry
IOLegacy
IOPLY
IOXML
InteractionStyle
InteractionWidgets
RenderingContextOpenGL2
RenderingCore
RenderingFreeType
RenderingGL2PSOpenGL2
RenderingOpenGL2
)
if (NOT VTK_FOUND)
message(FATAL_ERROR "MarbleShaderDemo: Unable to find the VTK build folder.")
endif()
# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(MarbleShaderDemo MACOSX_BUNDLE MarbleShaderDemo.cxx )
target_link_libraries(MarbleShaderDemo PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
TARGETS MarbleShaderDemo
MODULES ${VTK_LIBRARIES}
)
Download and Build MarbleShaderDemo¶
Click here to download MarbleShaderDemo and its CMakeLists.txt file. Once the tarball MarbleShaderDemo.tar has been downloaded and extracted,
cd MarbleShaderDemo/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:
./MarbleShaderDemo
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.