Toolkit Pipeline のチュートリアル

Toolkit Pipeline のチュートリアル

このドキュメントには、高度な方法で Toolkit を使用してシンプルなエンドツーエンドのパイプラインをセットアップする、テクニカル ディレクタ(TD)向けの段階的なチュートリアルを用意しています。このチュートリアルを終了した新しい Toolkit ユーザは、プラットフォームの基本的な要素と貴社固有のニーズに基づいたカスタマイズの方法を習得できます。また、すぐに使用できる Toolkit アプリと、アーティストのワークフローに合わせた利用方法についても紹介します。
このドキュメントは、Toolkit の設定を管理するユーザのみが使用可能な機能について説明します。詳細については、『Shotgun 統合ユーザ ガイド』を参照してください。

目次:

概要

            パイプライン

前提条件

      ソフトウェア

      Shotgun サイト

      設定済み Shotgun プロジェクト

      Shotgun Desktop

      追加ドキュメント:

Toolkit の設定

      Toolkit の設定を理解する

      コンテンツ作成ソフトウェアを設定する

            不要なものをクリーンアップする:

            ソフトウェア パス

      ファイルシステムの設定

ワークフローをカスタマイズする

      フックを理解する

      カスタム パブリッシュの概要

      カメラをパブリッシュする

      Alembic キャッシュをパブリッシュする

      シェーダをパブリッシュする

      レンダリング イメージをパブリッシュする

      Loader を設定する

アーティスト ワークフロー

      モデリング

      リギング

      サーフェス作成

      レイアウト

      アニメーション

      ライト

      合成

レビュー

上流工程の更新

結論

概要

以下のパイプラインは、10 週間に渡って連載された『2 人の男とツールキット』というタイトルのブログの一部として作成されました。このブログを確認すると、このチュートリアルでは記載されていない詳細とオプションが分かります。

パイプライン

このチュートリアルでは、アニメーションや視覚効果用のシンプルで一般的なパイプラインの作成について説明します。このチュートリアルに従うと、外観加工を介してモデリングのアセットをプロダクション シーンに転送するのに必要なすべての処理を提供するパイプラインを作成できます。次に、パイプラインの仕組みの概要を示します。



パイプラインの概要

分かりやすくするため、使用するデジタル コンテンツ作成(DCC)ソフトウェアは最小構成で Maya と Nuke に限定しています。また、パイプラインの工程で渡されるデータは、Maya ASCII ファイル、Alembic キャッシュ、およびレンダリング イメージ シーケンスに限定されます。

前提条件

ソフトウェア

このチュートリアルは、Shotgun を使用したプロダクション データのトラッキングと管理、MayaNuke の基本的な概要を理解していることを前提としています。また、Python で定義されたフックを使用して Toolkit の既定のアプリ動作を修正する必要があるため、Python スクリプトの作成経験も必須となります。

このチュートリアル内で参照する他の技術には GithubAlembic があります。

Shotgun サイト

Shotgun サイトを使用していない場合は、ここから無償体験版に登録できます。準備が完了すると、サイトの登録方法に関する説明が電子メールで届きます。サイトを起動して実行するには、Shotgun のスタートアップ ガイドを確認することをお勧めします。

設定済み Shotgun プロジェクト

サイトが表示されたら、Shotgun で新しいプロジェクトを作成して、プロダクション開始の準備に合わせて設定する必要があります。ここで、すべての必要な Shotgun エンティティが所定の場所にあり、正しくリンクされていることを確認します。このチュートリアルの場合、アセットシーケンスショット、およびタスクの各エンティティが必要で、既定では新しいプロジェクトで使用できる必要があります。作成する項目は次のとおりです。

  • アセット 2 つ: ティーポット キャラクタとテーブル プロップ
  • シーケンス 1 つ
  • 作成したシーケンスにリンクしたショット 1 つ
  • パイプラインの手順ごとのタスク

タスクは、関連付けられたパイプラインの手順に応じてショットまたはアセットにリンクされます。

次に、Shotgun で設定したプロジェクト エンティティのスクリーンショットを示します。



ティーポットとテーブルのアセット



ショット 1 つ(シーケンス リンクに注意)



設定済みタスク

Shotgun Desktop

Shotgun Desktop のダウンロードおよびインストールについては、次のチュートリアルの説明を参照してください。


Shotgun Desktop には、プロジェクト用に Toolkit をセットアップするプロセスを説明したインタフェースがあります。リンク先のチュートリアルを使用すると、ニーズに最適な既定の Toolkit 設定テンプレートとローカル ファイルシステム ストレージの設定方法を決定できます。

リンク先のドキュメントを使用してマシンに Desktop をインストールし、新しく設定した Shotgun プロジェクトを使用して「Shotgun Desktop を初めて実行する」セクションの手順を実行します。


設定テンプレートを選択する場合は既定の設定を必ず使用してください。




Project Set Up Wizard で選択した設定の場所をトラックします。そのパスを、このチュートリアルでのプロジェクト設定の指定に使用します。




初めて Toolkit プロジェクトをセットアップする場合は、プロダクション データのストレージ場所を定義するためのプロンプトも表示されます。




このチュートリアルを続行する前に Desktop のインストール チュートリアルを完了してください。

追加ドキュメント:

Shotgun または Toolkit の使用が初めてで、詳細なバックグラウンド情報が必要な場合は、次のリンクが役に立ちます。

Toolkit の設定

Toolkit の設定を理解する

Toolkit パイプラインを構築する上で重要なことは、Toolkit パイプライン設定の整理と動作の仕組みを理解することです。Toolkit 設定はパイプラインで使用するアプリケーションの統合を定義します。これには、使用するデジタル コンテンツ作成ソフトウェア(DCC)とこの DCC 内のアーティストが使用できる Toolkit のアプリ、エンジン、フレームワークの特定が含まれます。

Desktop インストールのチュートリアルで指定された設定場所は、Shotgun のプロジェクトの [パイプラインの設定](Pipeline Configurations)ページに記録されています。




マシンでパスを指定すると、次のようなディレクトリ構造が表示されます。




パイプライン作成時に主に意識するディレクトリは、coreenv、および hooks の 3 つです。これらのディレクトリ内のファイルはパイプラインの動作方法とユーザへの表示方法を制御します。次のセクションでは、プロジェクトを設定するためにこれらのディレクトリ内のファイルを修正する方法について説明します。

プロジェクトの設定に関する詳細については、次のドキュメントを参照してください。

コンテンツ作成ソフトウェアを設定する

Shotgun Desktop のセットアップ時に既定の設定を使用しているため、プロジェクトは Toolkit に統合されたすべての DCC を使用するように設定されます。このチュートリアルで説明したパイプラインにはすべての DCC が必要になるわけではありません。また、使用する DCC の既定のパスは、ファイルシステムのパスに一致するように修正する必要があります。以降のセクションでは、プロジェクトのコンテンツ作成ソフトウェアの設定について説明します。

不要なものをクリーンアップする:

最初の作業は Shotgun Desktop で使用しない DCC アプリケーションを削除することです。次に、Shotgun Desktop で表示される既定の DCC の例を示します。




Shotgun Desktop から DCC ランチャーをクリーンアップするには、config/env/project.yml 設定ファイルの tk-desktop エンジン設定を編集する必要があります。

Shotgun Desktop はプロジェクト レベルのコンテキストで実行される Toolkit エンジンです。環境ファイル内のエンジンとアプリの設定は次の形式になります。

engine:
<engine-name>:
    apps:
    <app-name>:
        <app-setting1>:
        <app-setting2>:
        ...
    <engine-setting1>:
    <engine-setting2>
    ...

既定のデスクトップ エンジンの設定は次のようになります。



注: 追加したファイルから大量の設定を読み込むには @ を使用します。

tk-multi-launchnuketk-multi-launchmaya など、各 DCC に対応するランチャー アプリのリストを確認できます。tk-desktop エンジンから DCC ランチャーを削除するには、設定からこの行を削除するだけです。




このチュートリアルでは、Maya、Nuke、Photoshop、および Screening Room 以外のランチャーの行をすべて削除します。Shotgun Desktop でプロジェクトに戻ると、次のような画面が表示されます。




Shotgun Desktop アプリケーションから DCC を起動するのとは別に、各 config/env/shotgun_*.yml ファイルでは、任意のコンテキストのブラウザで利用可能なランチャーを定義します。たとえば、shotgun_asset.yml で設定したランチャーは Shotgun の[アセット](Assets)ページの[プロジェクト アクション](Project Actions)メニューから使用できます。




project.yml のデスクトップ エンジンの設定と同様に、プロダクションでアーティストが必要とするランチャーのみを表示するように shotgun_*.yml ファイルから DCC を削除できます。

ソフトウェアのパス

パイプラインで使用する DCC が正しく参照されるようにするには、既定の設定で指定されたパスを更新する必要があります。DCC へのパスは config/env/includes/paths.yml ファイルに保存されています。このファイルで Maya のパス設定は次のように表示されます。




このファイルで、Maya、Nuke、および Photoshop のセクションを見つけて、ファイルシステム上のこれらのソフトウェア パッケージの場所を反映するようにパスを更新します。

ファイルシステムの設定

このチュートリアルで説明したシンプルなパイプラインは、既定の Toolkit 設定で指定されたディレクトリ構造を使用しています。プロジェクト ディレクトリ構造の設定方法については、ファイル システム設定リファレンスのドキュメントを参照してください。


このチュートリアルでは、既定の Toolkit の設定で定義されたテンプレートも使用します。テンプレート システムの詳細については、ファイル システム テンプレートの設定に関するドキュメントを参照してください。

ワークフローをカスタマイズする

ここで説明したシンプルなパイプラインを作成するには、アーティストが作業を(論理的に)開始する前に、Toolkit のコア アプリの設定とフックをカスタマイズする必要があります。

フックを理解する

ワークフローのカスタマイズを確認する前に、Toolkit フックの内容、その仕組み、および格納先を基本的に理解する必要があります。Toolkit フックを初めて使用する場合は、チュートリアルを進める前に以下のリンクのドキュメントを確認する必要があります。


以降のセクションでは、アプリのフックの修正またはカスタマイズについて説明します。それぞれのカスタマイズで次の手順を実行します。

  1. install ディレクトリ内でカスタマイズするアプリを特定し、サブディレクトリにあるフックを探します。インストールされたアプリの構造例とカスタマイズするフックの特定方法については、下図を参照してください。
  2. 設定の上位にある hooks ディレクトリにフックをコピーします(必要に応じて名前を変更)。
  3. 新しくオーバーライドされたフックが参照されるように、カスタマイズするアプリの設定で適切なフック設定を更新します。このチュートリアルのカスタマイズのほとんどは shot_step.yml ファイルで実行します。asset_step.yml 設定を変更する必要のある Publishing Shaders セクションは例外です。
  4. コードを変更して、フックのコピーをカスタマイズします。



Publisher アプリの scan_scene_tk-maya フックを特定し、設定のフック ディレクトリにコピーを作成。

カスタム パブリッシュの概要

このチュートリアルの次のセクションでは、カスタム パブリッシュのワークフローの作成に関連する手順について説明します。各セクションで説明されている基本的な手順は次のとおりです。

適切なエンジンの設定に新しいカスタム パブリッシュ タイプを追加する
パブリッシュするシーンの項目を識別するロジックを Publisher アプリの scan_scene フックに追加する
Publisher の secondary_pre_publish フックでパブリッシュする項目の検証を追加する
書き出しと登録のロジックを Publisher の secondary_publish フックに追加する

上記の箇条書きの色は、各手順の特定を簡単にするために以下のセクションに反映されています。

カメラをパブリッシュする

パイプラインに優れた柔軟性を実現する簡単なカスタマイズの方法は、スタンドアロンのカメラをパブリッシュできるようにすることです。これにより、カメラを一度作成すれば(通常はレイアウト内)、アニメーション、ライト、および合成など、他のすべてのパイプラインの手順でこのカメラを直接使用できるようになります。

続行する前に、Publisher アプリのドキュメントを確認して、このアプリのコンセプトの概要やその設定方法について理解してください。


カメラをパブリッシュできるようにするには、適切な環境の Publisher 設定に新しいセカンダリ パブリッシュ タイプを追加する必要があります。プロジェクトの shot_step.yml 環境で、tk-maya エンジン設定の Publishersecondary_outputs フィールドに次のエントリを追加します。

        - description: 'Publish a camera'
          display_group: Cameras
          display_name: Camera
          icon: 'icons/camera.png'
          name: camera
          publish_template: maya_shot_camera
          required: false
          scene_item_type: camera
          selected: false
          publish_group: false
          group_name: default
          tank_type: 'Camera'

YAML のヒント: YAML 構文で空のリストは [] で表されますが、空でないリストには括弧を使用しません。リストの各項目は 1 行ずつ先頭にダッシュを付けて表示します。この場合、secondary_outputs はディクショナリのリストで、上記のスニペットは 1 つのリスト項目です。インデント設定では、リスト項目の先頭のダッシュはリスト名と一体になる必要があります。そのため、secondary_outputs 内の唯一の項目は次のようになっています。

        secondary_outputs:
        - description: 'Publish a camera'
          display_group: Cameras
          display_name: Camera
          icon: 'icons/camera.png'
          name: camera
          publish_template: maya_shot_camera
          required: false
          scene_item_type: camera
          selected: false
          publish_group: false
          group_name: default
          tank_type: 'Camera'

これは、Publisher で認識すべきタイプ camera に別の 2 つ目のパブリッシュがあることを Publisher に示しています。

maya_shot_camera テンプレートは新しい 2 つ目の出力設定で指定されています。これにより、パブリッシュ フックがディスク上にカメラを書き込む場所を特定します。config/core/templates.yml ファイルで対応するテンプレートが指定されていることを確認する必要があります。次に例を示します。

    maya_shot_camera:
        definition: '@shot_root/publish/maya/camera/{name}.v{version}.ma'
        root_name: 'primary'


次に、ファイルのタイプ camera の項目を特定する方法を Publisher に指示する必要があります。このためには、Publisherscan_scene フックを修正します。次に、フックの execute メソッドに追加する必要があるスニペットを示します。

        # look for cameras to publish
        for camera in cmds.listCameras(perspective=True):
            items.append({"type": "camera", "name": camera})

このコードは、セッション内の各パース カメラの 2 つ目のパブリッシュ項目のリストにディクショナリを追加します。実際のプロダクション シナリオのコードはもっと高度で、特定の命名規則に一致するカメラまたはレンダリング可能としてマークされたカメラのみを追加することができます。


カスタム パブリッシュ タイプを追加する際の次の手順は、Publisher 2 つ目のパブリッシュ前フックを修正することです。このフックにより、指定した 2 つ目のパブリッシュ項目の評価と検証が可能になります。

execute メソッドのカメラ タイプに別の条件を追加する必要があります。この条件では、指定したカメラ項目の検証メソッドを呼び出します。

elif output["name"] == "camera":
    errors.extend(self.__validate_item_for_camera(item))

次に、追加する検証メソッドの例を抜粋して示します。

    def __validate_item_for_camera(self, item):
        """
        Validate that the item is valid to be exported to a camera

        :param item:    The item to validate
        :returns:       A list of any errors found during validation

        """

        # add error checking here!
        errors = []
        return errors


最後に、カメラ項目のパブリッシュを実際に処理する必要があります。これは Publisher2 つ目のパブリッシュ フックの execute メソッドで処理されます。パブリッシュ前フックと同様に、カメラの書き出し、登録、およびパブリッシュを実行するメソッドを呼び出すためにカメラ タイプの条件を追加します。追加する必要のある条件は次のようになります。

         elif output["name"] == "camera":
             try:
                 self.__publish_camera(item, output, work_template,
                                       primary_publish_path, sg_task, comment,
                                       thumbnail_path, progress_cb)
             except Exception, e:
                 errors.append("Publish failed - %s" % e)

パブリッシュの実際のロジックも追加する必要があります。次に、フックに追加する必要があるパブリッシュ カメラを処理するメソッドを示します。

クリックして publish camera メソッドを展開する...

    import re    # add this to the top of your file.

    def __publish_camera(self, item, output, work_template,
        primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Publish a shot camera and register with Shotgun.

        :param item:           The item to publish
        :param output:         The output definition to publish with
        :param work_template:  The work template for the current scene
        :param primary_publish_path: The path to the primary published file
        :param sg_task:        The Shotgun task we are publishing for
        :param comment:        The publish comment/description
        :param thumbnail_path: The path to the publish thumbnail
        :param progress_cb:    A callback that can be used to report progress
        """

        # determine the publish info to use
        #
        progress_cb(10, "Determining publish details")

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]
        tank_type = output["tank_type"]
        cam_name = item['name']
        fields['obj_name'] = cam_name
        fields['name'] = re.sub(r'[\W_]+', '', cam_name)

        # create the publish path by applying the fields
        # with the publish template:
        publish_template = output["publish_template"]
        publish_path = publish_template.apply_fields(fields)

        # ensure the publish folder exists:
        publish_folder = os.path.dirname(publish_path)
        self.parent.ensure_folder_exists(publish_folder)

        # determine the publish name
        publish_name = fields.get("obj_name")
        if not publish_name:
            publish_name = os.path.basename(publish_path)

        # Find additional info from the scene:
        #
        progress_cb(10, "Analysing scene")

        cmds.select(cam_name, replace=True)

        # write a .ma file to the publish path with the camera definitions
        progress_cb(25, "Exporting the camera.")
        cmds.file(publish_path, type='mayaAscii', exportSelected=True,
            options="v=0", prompt=False, force=True)

        # register the publish:
        progress_cb(75, "Registering the publish")
        args = {
            "tk": self.parent.tank,
            "context": self.parent.context,
            "comment": comment,
            "path": publish_path,
            "name": publish_name,
            "version_number": publish_version,
            "thumbnail_path": thumbnail_path,
            "task": sg_task,
            "dependency_paths": [primary_publish_path],
            "published_file_type":tank_type
        }
        tank.util.register_publish(**args)

このパイプラインで書き出しおよびパブリッシュされたカメラ ファイルは、カメラだけが含まれた Maya ファイルです。このファイルは、Loader アプリを使用して下流工程で参照できるようになりました。

Alembic キャッシュをパブリッシュする

既定の設定で提供される Alembic キャッシュ パブリッシュ サポートは、アセットのパブリッシュを対象としています。これはモデラから Mari などを使用するテクスチャ ペインタに Alembic キャッシュを渡す場合に最適ですが、ショット パイプライン下流工程の他の手順で使用するキャッシュ化されたジオメトリをショット コンテキストの Maya から書き出す場合には適していません。このワークフローの場合、詳細に文書化されたチュートリアルが既に用意されています。以下のチュートリアルに従って、ショット内での Alembic キャッシュのパブリッシュをセットアップします。

シェーダをパブリッシュする

パイプライン作成時のシェーダ管理は時間がかかり、複雑な作業になる場合があります。このパイプライン例の場合、Publisher アプリをカスタマイズして、サーフェス作成手順から 2 番目のパブリッシュとして Maya シェーダ ネットワークを書き出します。また、下流工程の参照時にシェーダが Alembic ジオメトリ キャッシュに再接続できるスピード重視のソリューションを作成します。

これは確かに非常に単純で不安定なシステムです。より堅牢なソリューションを作成する場合、サーフェス キャラクタの代替表現と、テクスチャとして外部イメージを使用するというアセット管理の側面を取り入れることになります。この例は、実際のソリューションを作成する際の第一歩として使用してください。


このカスタマイズの場合、カメラ パブリッシュと同様に、最初のステップは環境設定に他の 2 番目のパブリッシュ タイプを追加することです。シェーダはアセットの作業中に上流工程で作成されるため、tk-maya sectionasset_step.yml ファイルに次のコードを追加します。

        - description: Publish shader network for all geometry in the scene
          display_group: Shader Network
          display_name: Maya Shader Network
          icon: 'icons/maya_shader_network_publish.png'
          name: maya_shader_network
          publish_template: maya_asset_shader_network
          required: false
          scene_item_type: shader_network
          selected: false
          publish_group: false
          group_name: default
          tank_type: 'Maya Shader Network'

Alembic の書き出しと同様に、設定のこのセクションは、shader_network タイプで定義されたタイプに固有の追加コードをトリガするさまざまなフックによって使用されます。この別のフィールドでは、追加の書き出しタイプを Publisher アプリで表示する方法、このタイプが必要かどうか、ディスクへの書き込み時に使用するテンプレートなどが定義されます。

このテンプレート定義をプロジェクトの config/core/templates.yml 設定ファイルに追加します。

    # The location where maya shader networks are stored on disk
    maya_asset_shader_network:
        definition: '@asset_root/publish/maya/surfacing/{name}.v{version}.ma'
        root_name: 'primary'


Publisher にこの新しいタイプを探すように指示したので、セッション内でシェーダ ネットワークを特定するように scan_scene フックを修正する必要があります。次のコードを scan_scene フックに追加します。

        # export shader networks for any root level meshes.
        for grp in cmds.ls(assemblies=True):
            if cmds.ls(grp, dag=True, type="mesh"):
                items.append({"type":"shader_network", "name":grp})

上記のコードは、すべてのルートレベルのメッシュの items リストにディクショナリを追加します。パブリッシュ フックは、Publisher UI で選択したメッシュのシェーダを書き出すためにこの項目を特定します。


前のセクションで確認したとおり、secondary_pre_publish フックは選択した項目を検証するために実行されます。このフックの execute メソッドで、次のコードを既存の条件に追加して、シェーダ ネットワーク固有の検証コードを呼び出します。

    elif output["name"] == "maya_shader_network":
        errors.extend(self.__validate_item_for_maya_shader_network_publish(item))

次に、検証メソッドの抜粋例を示します。

    def __validate_item_for_maya_shader_network_publish(self, item):

        """
        Validate that the item is valid to be exported to a maya shader network

        :param item: The item to validate
        :returns: A list of any errors found during validation that should be reported
                  to the artist
        """

        # add error checking here!
        errors = []
        return errors


UI の Publish ボタンをクリックすると、実際のパブリッシュ ルーチンが実行されます。以前のカスタマイズから分かるとおり、ルーチンは secondary_publish フック内に存在します。次に、シェーダ ネットワークをパブリッシュするための呼び出しを既存の条件に追加します。

            elif output["name"] == "maya_shader_network":
                try:
                    self.__publish_maya_shader_network(item, output,
                        work_template, primary_publish_path, sg_task, comment,
                        thumbnail_path, progress_cb)
                except Exception, e:
                    errors.append("Publish failed - %s" % e)

さらに、シェーダ ネットワークをパブリッシュするためのメソッドを追加します。

クリックして publish shader メソッドを展開する...

    def __publish_maya_shader_network(self, item, output, work_template,
        primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Publish shader networks for the asset and register with Shotgun.

        :param item:                    The item to publish
        :param output:                  The output definition to publish with
        :param work_template:           The work template for the current scene
        :param primary_publish_path:    The path to the primary published file
        :param sg_task:                 The Shotgun task we are publishing for
        :param comment:                 The publish comment/description
        :param thumbnail_path:          The path to the publish thumbnail
        :param progress_cb:             A callback that can be used to report progress

        """

        # determine the publish info to use
        #
        progress_cb(10, "Determining publish details")

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]
        tank_type = output["tank_type"]
        obj_name = item['name']
        fields['obj_name'] = obj_name
        fields['name'] = re.sub(r'[\W_]+', '', obj_name)

        # create the publish path by applying the fields
        # with the publish template:
        publish_template = output["publish_template"]
        publish_path = publish_template.apply_fields(fields)

        # ensure the publish folder exists:
        publish_folder = os.path.dirname(publish_path)
        self.parent.ensure_folder_exists(publish_folder)

        # determine the publish name:
        publish_name = fields.get("obj_name")
        if not publish_name:
            publish_name = os.path.basename(publish_path)

        # Find additional info from the scene:
        #
        progress_cb(10, "Analysing scene")

        # clean up any hookup nodes that existed before
        _clean_shader_hookup_script_nodes()

        # there's probably a better way to do this. i am jon snow (i know
        # nothing)
        shading_groups = set()
        shad_group_to_obj = {}
        if cmds.ls(obj_name, dag=True, type="mesh"):
            faces = cmds.polyListComponentConversion(obj_name, toFace=True)
            for shading_group in cmds.listSets(type=1, object=faces[0]):
                shading_groups.add(shading_group)
                shad_group_to_obj[shading_group] = obj_name

        shaders = set()
        script_nodes = []
        for shading_group in list(shading_groups):
            connections = cmds.listConnections(
                shading_group, source=True, destination=False)
            for shader in cmds.ls(connections, materials=True):
                shaders.add(shader)
                obj_name = shad_group_to_obj[shading_group]

                # can't seem to store arbitrary data in maya in any
                # reasonable way. would love to know a better way to
                # do this. for now, just create a script node that
                # we can easily find and deduce an object name and
                # shader name. Yes, this is hacky.
                script_node = cmds.scriptNode(
                    name="SHADER_HOOKUP_" + obj_name,
                    scriptType=0, # execute on demand.
                    beforeScript=shader,
                )

                script_nodes.append(script_node)

        if not shaders:
            progress_cb(100, "No shader networks to export.")
            return

        select_nodes = list(shaders)
        select_nodes.extend(script_nodes)

        cmds.select(select_nodes, replace=True)

        # write a .ma file to the publish path with the shader network definitions
        progress_cb(25, "Exporting the shader network.")
        cmds.file(
            publish_path,
            type='mayaAscii',
            exportSelected=True,
            options="v=0",
            prompt=False,
            force=True
        )

        # clean up shader hookup nodes. they should exist in the publish file
        # only.
        _clean_shader_hookup_script_nodes()

        # register the publish:
        progress_cb(75, "Registering the publish")
        args = {
            "tk": self.parent.tank,
            "context": self.parent.context,
            "comment": comment,
            "path": publish_path,
            "name": publish_name,
            "version_number": publish_version,
            "thumbnail_path": thumbnail_path,
            "task": sg_task,
            "dependency_paths": [primary_publish_path],
            "published_file_type":tank_type
        }

        tank.util.register_publish(**args)

    def _clean_shader_hookup_script_nodes():

        # clean up any existing shader hookup nodes
        hookup_prefix = "SHADER_HOOKUP_"
        shader_hookups = {}
        for node in cmds.ls(type="script"):
            if node.startswith(hookup_prefix):
                cmds.delete(node)

書き出しとパブリッシュのロジックを設定すると、シェーダ ネットワーク パブリッシュの作成が開始されます。下流工程でこのパブリッシュを使用するには、Loader アプリを修正する必要があります。


この例でパブリッシュされているシェーダは Maya ファイルだけのため、既存のロジックを変更しなくても Loader アプリで参照することができます。必要な変更は、シェーダをファイル内で参照した後に、シェーダ バックアップをフックするための新しいロジックを適切なメッシュに追加するだけです。

Loader のカスタム action_hook に次のロジックを追加します。

def _hookup_shaders(reference_node):

    hookup_prefix = "SHADER_HOOKUP_"
    shader_hookups = {}
    for node in cmds.ls(type="script"):
        if not node.startswith(hookup_prefix):
            continue
        obj_pattern = node.replace(hookup_prefix, "") + "\d*"
        obj_pattern = "^" + obj_pattern + "$"
        shader = cmds.scriptNode(node, query=True, beforeScript=True)
        shader_hookups[obj_pattern] = shader

    for node in (cmds.referenceQuery(reference_node, nodes=True) or []):
        for (obj_pattern, shader) in shader_hookups.iteritems():
            if re.match(obj_pattern, node, re.IGNORECASE):
                # assign the shader to the object
                cmds.file(unloadReference=reference_node, force=True)
                cmds.setAttr(reference_node + ".locked", False)
                cmds.file(loadReference=reference_node)
                cmds.select(node, replace=True)
                cmds.hyperShade(assign=shader)
                cmds.file(unloadReference=reference_node)
                cmds.setAttr(reference_node + ".locked", True)
                cmds.file(loadReference=reference_node)
            else:
                print "NODE: " + node + " doesn't match " + obj_pattern

_create_reference() メソッドの最後にある _hookup_shaders() に呼び出しを忘れずに追加してください。

このすべてのカスタマイズは、tk-framework-simple リポジトリで定義されたフックと tk-config-simple リポジトリの asset_step 環境に実装します。

レンダリング イメージをパブリッシュする

このシンプルなパイプラインをカスタマイズし、ライトから合成までの引き継ぎ用として Maya から Nuke にレンダリング イメージをパブリッシュする機能を追加します。この受け渡しを実現するために、ディスク上のレンダリング イメージへのパスを表すテンプレートを最初に作成します。プロジェクトの config/core/templates.yml 設定ファイルに次のテンプレートを追加します。

maya_shot_render:
  definition: '@shot_root/work/images/{maya.camera_name}/{maya.layer_name}/v{version}/{name}.{SEQ}.exr'
  root_name: 'primary'

テンプレート文字列 maya.layer_namemaya.camera_name が使用されています。この文字列を同じファイルのキー セクションに追加すると、カスタマイズしたパブリッシュ フックがディスク上のレンダリング イメージの検索時に設定されるようにプレースホルダとして機能します。

    # reserve a template key for the maya camera name and render layer name
    maya.camera_name:
        type: str

    maya.layer_name:
        type: str


テンプレートを設定すると、Alembic キャッシュやシェーダ ネットワークと同様に、適切な環境の Publisher 設定にレンダリング イメージの新しい 2 番目の出力タイプを追加する必要があります。次のコードを shot_step.yml に追加します。

        - description: 'Publish a rendered image sequence'
          display_group: Renders
          display_name: Rendered
          icon: 'icons/publish_nuke_writenode.png'
          name: rendered_image
          publish_template: maya_shot_render
          required: false
          scene_item_type: rendered_image
          selected: false
          publish_group: false
          group_name: default
          tank_type: 'Rendered Image'

レンダリング イメージ タイプの 2 番目の出力定義は、レンダリング フレームを Publisher で表示する方法を制御するのに役立ちます。フレームは Publisher の表示中にレンダリングされるため、publish_template フィールドは少し分かりづらくなります。これは、パブリッシュ フックの実行時の追加ファイルの書き込み先を制御するテンプレートを使用する他の 2 番目の Maya パブリッシュとは異なります。


また、このカスタマイズが機能するように修正した最初のフックは、Publisherscan_scene フックです。現在の Maya セッションで項目を検出する他のカスタマイズとは異なり、このコードはディスク上のレンダリング フレームを検出します。このコードを scan_scene フックに追加します。

        # we'll use the engine to get the templates
        engine = tank.platform.current_engine()

        # get the current app
        app = self.parent

        # look up the template for the work file in the configuration
        # will get the proper template based on context (Asset, Shot, etc)
        work_template = app.get_template("template_work")
        work_template_fields = work_template.get_fields(scene_name)
        version = work_template_fields["version"]

        # get all the secondary output render templates and match them against
        # what is on disk
        secondary_outputs = app.get_setting("secondary_outputs")
        render_outputs = [out for out in secondary_outputs if out["tank_type"] == "Rendered Image"]
        for render_output in render_outputs:

            render_template = app.get_template_by_name(render_output["publish_template"])

            # now look for rendered images. note that the cameras returned from 
            # listCameras will include full DAG path. You may need to account 
            # for this in your, more robust solution, if you want the camera name
            # to be part of the publish path. For my simple test, the cameras 
            # are not parented, so there is no hierarchy.

            # iterate over all cameras and layers
            for camera in cmds.listCameras():
                for layer in cmds.ls(type="renderLayer"):

                    # apparently maya has 2 names for the default layer. I'm
                    # guessing it actually renders out as 'masterLayer'.
                    layer = layer.replace("defaultRenderLayer", "masterLayer")

                    # these are the fields to populate into the template to match
                    # against
                    fields = {
                        'maya.camera_name': camera,
                        'maya.layer_name': layer,
                        'name': layer,
                        'version': version,
                    }

                    # match existing paths against the render template
                    paths = engine.tank.abstract_paths_from_template(
                        render_template, fields)

                    # if there's a match, add an item to the render 
                    if paths:
                        items.append({
                            "type": "rendered_image", 
                            "name": layer,

                            # since we already know the path, pass it along for
                            # publish hook to use
                            "other_params": {
                                # just adding first path here. may want to do some
                                # additional validation if there are multiple.
                                'path': paths[0],
                            }
                        })

変更の目的は、maya_shot_render テンプレートに一致するレンダリング イメージがディスク上にあるかどうかを判断するためです。ロジックには、現在の Maya セッションのカメラとレンダリング レイヤの反復処理とその名前を使用したレンダリング テンプレートの評価が含まれます。評価したパスに一致するフレームがディスク上に存在する場合は、パブリッシュ対象が存在します。また、コードはパブリッシュ フックが同じ作業を実行しないように特定したレンダリング イメージもトラックします。


レンダリング イメージがパブリッシュする項目のリストに追加されます。secondary_pre_publish フックを修正して、レンダリング フレームが有効で、状態が良好であることを確認する必要があります。これは前回のカスタマイズの確認後と同じです。

        elif output["name"] == "rendered_image":
            errors.extend(self.__validate_item_for_rendered_image_publish(item))

次に、検証メソッドの抜粋例を示します。

    # validate rendered images...
    def __validate_item_for_rendered_image_publish(self, item):

        """
        Validate that the item is valid to be exported as a rendered image

        :param item:    The item to validate
        :returns:       A list of any errors found during validation
        """

        # add error checking here. here you can validate the rendered images in
        # whatever way you need to. right number of frames, no missing frames,
        # able to generate a thumbnail, all expected layers present, whatever
        # else you need.
        errors = []
        return errors

次に、実際のプロダクションに追加できるいくつかの潜在的な検証手順を示します。

  • すべてのフレームが存在する
  • ファイル サイズに一貫性がある
  • 権限が適切である
  • 2 番目のファイルが存在する(サムネイルや QuickTime など)


最後の変更は、新しいタイプを処理できるように secondary_publish フックを修正することです。このフックにレンダリング イメージをパブリッシュするメソッドを呼び出す条件を追加します。

            elif output["name"] == "rendered_image":
                try:
                   self.__publish_rendered_images(item, output,
                       work_template, primary_publish_path, sg_task, comment,
                       thumbnail_path, progress_cb)
                except Exception, e:
                   errors.append("Publish failed - %s" % e)

次に、レンダリング イメージのパスの登録とパブリッシュを実行するメソッドを追加します。

クリックして publish rendered images メソッドを展開する...

    def __publish_rendered_images(self, item, output, work_template,
        primary_publish_path, sg_task, comment, thumbnail_path, progress_cb):
        """
        Publish rendered images and register with Shotgun.

        :param item:                    The item to publish
        :param output:                  The output definition to publish with
        :param work_template:           The work template for the current scene
        :param primary_publish_path:    The path to the primary published file
        :param sg_task:                 The Shotgun task we are publishing for
        :param comment:                 The publish comment/description
        :param thumbnail_path:          The path to the publish thumbnail
        :param progress_cb:             A callback that can be used to report progress
        """

        # determine the publish info to use
        #
        progress_cb(10, "Determining publish details")

        # get the current scene path and extract fields from it
        # using the work template:
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        fields = work_template.get_fields(scene_path)
        publish_version = fields["version"]
        tank_type = output["tank_type"]

        # this is pretty straight forward since the publish file(s) have
        # already been created (rendered). We're really just populating the
        # arguments to send to the sg publish file registration below.
        publish_name = item["name"]

        # we already determined the path in the scan_scene code. so just
        # pull it from that dictionary.
        other_params = item["other_params"]
        publish_path = other_params["path"]

        # register the publish:
        progress_cb(75, "Registering the publish")
        args = {
            "tk": self.parent.tank,
            "context": self.parent.context,
            "comment": comment,
            "path": publish_path,
            "name": publish_name,
            "version_number": publish_version,
            "thumbnail_path": thumbnail_path,
            "task": sg_task,
            "dependency_paths": [primary_publish_path],
            "published_file_type": tank_type
        }

        tank.util.register_publish(**args)

コードには、other_params ディクショナリのパブリッシュ パスが表示されます。レンダリング イメージのパスは、上記の説明のとおり scan_scene hook によって特定されるため、再び検索する必要はありません。実際のプロダクション パイプラインでは、ファイル権限の設定や参照先の作成など、ここで処理を追加する場合もあります。

すべてを設定したら、Shotgun にパブリッシュしたレンダリング イメージを登録すると、変更を追加しなくても Nuke の Loader で使用できるようになります。



レンダリング イメージの 2 番目のパブリッシュ



Nuke Loader のレンダリング イメージ

Loader を設定する

これで新しい 2 番目のパブリッシュ タイプを複数追加しました。パイプラインの各手順で新しい上流工程用の参照を作成するために、アプリがこのタイプを認識していることを確認する必要があります。上流工程のアーティストが作業を繰り返してパブリッシュするため、パブリッシュされたファイルを参照すると、Scene Breakdown アプリで新しいバージョンをすぐにスキャンできるようになります。Scene Breakdown アプリはすぐに使用可能で、Maya の参照の更新をサポートします。


Loader アプリで追加された新しい 2 番目のパブリッシュ タイプを認識させるには、設定の shot_step.ymlaction_mappings セクションを更新します。

tk-multi-loader2:
  action_mappings:
    Alembic Cache: [reference, import]
    Camera: [reference, import]
    Maya Shader Network: [reference, import]
    Rendered Image: [texture_node]
    Maya Scene: [reference, import]

新しいアクション マッピングを追加すると、Loader には参照用にカスタマイズした 2 番目のパブリッシュ タイプが表示されます。

アーティスト ワークフロー

これですべてのカスタマイズを完了したので、すべてがどのように機能するかを確認します。次のセクションでは、モデリングから合成までのすべてのパイプラインを確認します。

モデリング

シンプルなパイプラインの最初の手順はモデリングです。Configured Shotgun Project と呼ばれる前提条件セクションで Shotgun にティーポット キャラクタ アセットを作成しておきます。作成していない場合は、戻ってアセットを作成してから作業を続けます。

Shotgun Desktop から Maya を起動します。次に、ティーポットをモデリングするか、指定のティーポットをダウンロードおよび読み込みます。




ティーポットの外観に問題がなければ、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ティーポット アセットの Model タスクを指定し、ファイル名を入力します。




次に、Shotgun > Publish ... メニューから Publisher を起動します。




カメラ アイコンをクリックして、ティーポットのスクリーンショットを作成してコメントを入力します。Publish をクリックして、プロセスが完了するまで待機します。




下流工程のユーザが使用する Maya ファイルとしてモデルのパブリッシュに成功しました。

テーブル プロップをモデリング(またはダウンロード)およびパブリッシュしてこのセクションを繰り返します。終了したら、ティーポットとテーブルのアセットごとにモデルが Maya ファイルとしてパブリッシュされます。

リギング

モデルがパブリッシュされたら、次の手順ではリグを作成してパブリッシュします。

Shotgun Desktop から Maya を起動します。起動したら、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ティーポット アセットの Rig タスクを指定し、ファイル名を入力します。




ここで、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開いていると、パブリッシュしたティーポット モデルを選択してシーンでこのモデルを参照できるようになりました。




ここでシーンにロードされたティーポット モデルにリグを設定します。




リグをパブリッシュする準備が完了したら、Shotgun > Publish ... メニューから Publisher を起動します。モデルに実行したのと同じ方法でリグ付きアセットをパブリッシュします。この場合、リグの Alembic キャッシュをパブリッシュする必要はありません。ただし、パブリッシュしても悪影響はありません。




テーブル プロップにリグを設定してパブリッシュし、このセクションを繰り返します。終了したら、ティーポットとテーブルのアセットごとにリグが Maya ファイルとしてパブリッシュされます。

サーフェス作成

ワークフローのアセットの最後の手順では、パブリッシュされたモデルのサーフェスを作成して、そのシェーダ ネットワークをパブリッシュします。

Shotgun Desktop から Maya を起動します。起動したら、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ティーポット アセットの Texturing and Shading タスクを指定し、ファイル名を入力します。




以前のリギング手順と同様に、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開いていると、パブリッシュしたティーポット モデルを選択してシーンでこのモデルを参照できるようになりました。

これでモデルが設定されました。ティーポットのサーフェスを作成します。




完了したら、Shotgun > Publish ... メニューを使用して Publisher アプリを起動し、シェーダ ネットワークをパブリッシュします。モデルに実行したのと同じ方法でサーフェス作成済みアセットをパブリッシュします。この場合、Maya シェーダ ネットワークの 2 番目の項目が有効になっていることを確認します。




テーブル プロップのサーフェスを作成してパブリッシュし、このセクションを繰り返します。終了したら、ティーポットとテーブルのアセットごとにシェーダが Maya ファイルとしてパブリッシュされます。

レイアウト

ここではワークフローのショット制作手順を確認します。最初の手順では、ショットのカメラのアニメーションやフレーム内でのティーポットとテーブル アセットの位置など、ショットの基本的なレイアウトを決定します。

Shotgun Desktop から Maya を起動します。起動したら、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ショットの Camera タスクを指定し、ファイル名を入力します。




ここで、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開くことにより、パブリッシュしたリグを選択してシーンでこのリグを参照できるようになりました。




シーン内にティーポットとテーブルのリグがあるので、任意の場所に配置します。ショットのカメラを作成してアニメートします。




完了したら、Shotgun > Publish ... メニューを使用して Publisher アプリを起動し、ショットのレイアウト内のすべてのコンポーネントをパブリッシュします。2 つのアセットの Alembic キャッシュとカメラの 2 番目の出力を必ずパブリッシュしてください。




アニメーション

ショットのレイアウトのパブリッシュが完了したので、ショット内のアセットにアニメーションを追加します。

Shotgun Desktop から Maya を起動します。起動したら、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ショットの Animation タスクを指定し、ファイル名を入力します。




ここで、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開くことにより、Camera タスクからパブリッシュした Maya シーン ファイルを選択して、シーンでこのファイルを参照できるようになりました。アセットの参照が完了したら、Loader を使用してパブリッシュしたカメラも取り込みます。




シーンのレイアウトが設定されたので、必要に応じてリグをアニメートします。




完了したら、Shotgun > Publish ... メニューを使用して Publisher アプリを起動し、ショットのレイアウト内のすべてのコンポーネントをパブリッシュします。2 つのアセットの Alembic キャッシュを必ずパブリッシュしてください。この手順では、カメラの変更はカメラ タスクから実行されることが多いため、カメラを再びパブリッシュする必要はないかもしれません。




ライト

Lighting で、アセットとショット用に作成したパブリッシュ ファイルをすべて取り込みます。

Shotgun Desktop から Maya を起動します。起動したら、Maya インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ショットの Lighting タスクを指定し、ファイル名を入力します。




ここで、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開くことにより、次のパブリッシュ済み項目を参照および作成できるようになりました。

  • レイアウトのカメラ
  • アニメーションからのテーブルとティーポットの Alembic キャッシュ
  • テーブルとティーポットのシェーダ ネットワーク




その結果、上流工程で生成された項目がすべて組み合わせられます。




次の手順では、必要に応じてシーン内のライトを配置します。




その後、レンダリング レイヤをセットアップしてディスクにレンダリングする必要があります。レンダリング レイヤの出力パスが Publishing Rendered Images セクションで定義したテンプレートと一致することを確認する必要があります。

完了したら、Shotgun > Publish ... メニューを使用して Publisher アプリを起動し、レンダリング イメージ レイヤをパブリッシュします。




合成

ショット ワークフローの最後の手順は合成です。ここでは、ライトからパブリッシュされたレンダリング要素、レイアウト内のショットのカメラ、およびアニメーションからパブリッシュされた Alembic キャッシュをロードすることができます。必要なすべてのデータを Nuke にロードしたら、最後のショットをレンダリングできます。

Shotgun Desktop から Nuke を起動します。起動したら、Nuke インタフェース上部の Shotgun > Shotgun File Manager ... メニューで File Save ... ボタンをクリックします。File Manager インタフェースで、ショットの Shot Finaling タスクを指定し、ファイル名を入力します。




ここで、Shotgun > Load ... メニュー アクションを使用して Loader アプリを起動します。Loader アプリを開くことにより、Lighting タスクからパブリッシュしたレンダリング要素を選択して、シーンでこの要素を参照できるようになりました。




Loader アプリは、読み込んだ項目ごとに Nuke で読み取りノードを作成します。




これでレンダリング要素がシーンに読み込まれました。ショットを終了します。この作業が完了すると、Shotgun Quick Daily ノードを作成できます。このため、コンポーネントの出力から Shotgun でバージョンを作成できるようになります。




Shotgun Quick Daily ノードに加えて、Shotgun Toolkit でコンポーネントの出力を管理するために Shotgun の Write Node も利用可能になります。




Shotgun Write Node を配置すると、Shotgun > Publish ... メニューから Publisher アプリを起動してコンポーネントの出力をパブリッシュできます。




レビュー

制作中にショットで実行した作業をレビューする必要がでてきます。ShotgunQuickDaily ノードに関連した上記の合成セクションで説明したとおり、DCC アプリケーションで作成したメディアを Shotgun に送信することができます。


Shotgun に登録されたメディアを参照するために、Screening Room アプリを Shotgun Desktop から起動できます。




Screening Room が開くと、利用可能なメディアにリンクされたエンティティであるショットまたはアセット別にこのメディアをフィルタできます。




表示するメディアをダブル クリックし、RV の再生コントロールを使用してメディアを再生します。

上流工程の更新

プロダクション パイプラインの各ステップでアーティストは作業を繰り返して新しいバージョンをパブリッシュします。Toolkit には Scene Breakdown アプリがあり、参照中のパブリッシュ ファイルで期限が切れているバージョンを表示します。


アーティストのワークフローの一部として、ファイルが上流工程の最新の作業と同じかどうかを確認するために更新をチェックする必要があります。このためには、すべてのパイプラインの手順で、Shotgun > Scene Breakdown ... を使用して Maya の Shotgun メニューから Scene Breakdown アプリを起動します。

このアプリは、ファイル内にある認識済みのパブリッシュされたすべてのファイルを表示します。期限切れの参照は「x」の付いた赤色の点で表示されます。最新の参照はチェック マークの付いた緑色の点で表示されます。



Scene Breakdown アプリ。左側には更新前のファイルの参照状態が表示されます。
右側ではカメラのバージョンが 6 から 11 に更新されています。

期限切れの参照を更新するには、期限切れの参照の行を選択して Update Selected ボタンをクリックするだけです。上図は更新前後のアプリの状態を示しています。

すべての項目が緑色に点灯した場合、ファイルは上流工程の最新のパブリッシュ ファイルと同じ状態です。

結論

このチュートリアルが、Toolkit を使用して独自のカスタム パイプラインを作成する際の第一歩になるはずです。スタジオ固有のニーズに合わせて既存の Toolkit アプリを拡張する方法について理解できたことでしょう。

機能やワークフローを既定の Toolkit アプリで実現できないと感じた場合は、独自のアプリをいつでも作成できます。初めて Toolkit アプリを作成する場合は、ここを参照してください。

このチュートリアルの詳細または Shotgun や Toolkit の概要に関して質問がある場合は、チケットを送信してください。

フォローする

0 コメント

ログインしてコメントを残してください。