カスタムシェーダを使おうとして動かないときに、生成されたシェーダを確認したいことがある。
MapperのObserverを追加してコンパイルされるシェーダのソースコードを表示できる。
なおエラーがある場合はどのみちエラー出力で表示されるのでここまでしなくていい。
#include <iostream> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> //円筒とその表示に必要 #include <vtkCylinderSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkPointData.h> // シェーダ関係のinclude #include <vtkShaderProgram.h> #include <vtkShaderProperty.h> #include <vtkOpenGLPolyDataMapper.h> //////////////////////////////// #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"psapi.lib") #pragma comment(lib,"dbghelp.lib") #pragma comment(lib,"ws2_32.lib") //必須 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); // データに色情報を追加 void SetColor(vtkSmartPointer<vtkPolyData> data, const char* scalarname, std::array<unsigned char, 3> rgb) { size_t PointNum = data->GetNumberOfPoints(); vtkSmartPointer<vtkUnsignedCharArray> colorsNew = vtkSmartPointer<vtkUnsignedCharArray>::New(); colorsNew->SetNumberOfComponents(3); colorsNew->SetName(scalarname); for (int i = 0; i < PointNum; i++) { // ランダムな色を作成 double r = vtkMath::Random(0.0, 255.0); double g = vtkMath::Random(0.0, 255.0); double b = vtkMath::Random(0.0, 255.0); colorsNew->InsertNextTuple3(r,g,b); } data->GetPointData()->AddArray(colorsNew); } void setShader(vtkSmartPointer<vtkActor> actor) { auto shaderProperty = actor->GetShaderProperty(); shaderProperty->AddVertexShaderReplacement( "//VTK::Color::Impl", true, R"( //VTK::Color::Impl // 頂点カラーから赤を除去 vertexColorVSOutput = vec4( 0.0, vertexColorVSOutput.g, vertexColorVSOutput.b, 1.0 ); )", false); }
class MyShaderCallback : public vtkCommand { public: static MyShaderCallback* New() { return new MyShaderCallback; } void Execute(vtkObject* caller, unsigned long eventId, void* callData) override { if (eventId == vtkCommand::UpdateShaderEvent && callData) { auto* program = static_cast<vtkShaderProgram*>(callData); if (!program) { return; } // 頂点シェーダとフラグメントシェーダのソースコードを取得 const std::string& vertSrc = program->GetVertexShader()->GetSource(); const std::string& fragSrc = program->GetFragmentShader()->GetSource(); std::cout << "=== Vertex Shader (頂点シェーダ)===" << std::endl; std::cout << "=== " << std::endl; std::cout << "=== " << std::endl << std::endl; std::cout << vertSrc << std::endl; std::cout << "///////////////////////////////////////////////" << std::endl; std::cout << "///////////////////////////////////////////////" << std::endl; std::cout << "///////////////////////////////////////////////" << std::endl; std::cout << "///////////////////////////////////////////////" << std::endl; std::cout << "=== Fragment Shader (フラグメントシェーダ)===" << std::endl; std::cout << "=== " << std::endl; std::cout << "=== " << std::endl << std::endl; std::cout << fragSrc << std::endl; } } };
int main(int /*argc*/, char** /*argv*/) { // シリンダー作成 vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New(); cylinder->SetResolution(50); cylinder->SetHeight(3.0); cylinder->SetRadius(1.0); cylinder->Update(); // actorを作成 vtkSmartPointer<vtkPolyData> points = cylinder->GetOutput(); SetColor(points, "ColorsRed", { 255,0,0 }); SetColor(points, "ColorsBlue", { 0,0,255 }); // actorを作成 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputData(points); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); ////////////////////////////////////// // 使用する色をAddArrayで指定したスカラー値を使用するように設定 mapper->SetScalarVisibility(1); // スカラー値を使用して色をつける設定 mapper->SetScalarModeToUsePointFieldData(); // スカラー値はポイントデータに設定されているものを使用 mapper->SetColorModeToDefault(); // カラーモードをデフォルトに設定 // 色の切り替えも有効 mapper->SelectColorArray("ColorsBlue"); mapper->Modified();// マッパーを更新 ////////////////////////////////////// // カスタムシェーダを設定 setShader(actor); mapper->Modified();// マッパーを更新
vtkOpenGLPolyDataMapper* glMapper = vtkOpenGLPolyDataMapper::SafeDownCast(mapper); if (!glMapper) { std::cout << "Shader is not OpenGL based." << std::endl; } else { // シェーダの更新イベントを監視 vtkNew<MyShaderCallback> callback; glMapper->AddObserver(vtkCommand::UpdateShaderEvent, callback); }
////////////////////////////////////// auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddActor(actor); renderer->ResetCamera(); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); ////////////////////////////////////// auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetInteractor(interactor); renderWindow->Render(); interactor->Start(); //イベントループへ入る return 0; }