前回に続き、今回はマテリアルを作成します。
マテリアルの作成
マテリアルを作成します。マテリアルとは次に挙げるシェーダーネットワークのコンテナとして機能させるもので,この考えを理解しておくことが重要です。
from pxr import Usd, UsdGeom, UsdShade, Sdf, Gf
def create_material(stage, path):
material = UsdShade.Material.Define(stage, path)
return material
シェーダーの作成
シェーダーを作成します。先ほども述べたように,マテリアルはコンテナですからシェーダーはマテリアルの Sdf パスの下に作成するようにします。まず,PBR シェーダー(UsdPreviewSurface)から作成していきます。metallic と roughness の両プロパティに加えて,マテリアルの色と透過度も設定してみました(USDPreviewSurface については公式マニュアルのここに詳しい説明があります)。
def create_shader(stage, path):
shader = UsdShade.Shader.Define(stage, path)
shader.CreateIdAttr('UsdPreviewSurface')
# Inputs
shader.CreateInput('metallic', Sdf.ValueTypeNames.Float).Set(0.0)
shader.CreateInput('roughness', Sdf.ValueTypeNames.Float).Set(0.4)
shader.CreateInput('diffuseColor', Sdf.ValueTypeNames.Color3f).Set(Gf.Vec3f(1, 0, 1)) # Magenta
shader.CreateInput('opacity', Sdf.ValueTypeNames.Float).Set(1)
return shader
先ほどのマテリアルの定義を書き換えて,シェーダーの surface output に接続するための「ターミナル」を設けるようにします。
def create_material(stage, path):
material = UsdShade.Material.Define(stage, path)
# Terminal outputs
material.CreateSurfaceOutput()
return material
マテリアルと PBR シェーダーをつなぎ,さらにメッシュをマテリアルにバインドします。これらはメインプログラムで行うことにします(ステージ作成からメッシュ作成までは前回までの記事と同じです)。
if __name__ == '__main__':
# ステージ作成
stage = create_stage()
# ルートノード作成
rootNode = create_node(stage, '/World', is_defaultPrim=True)
# メッシュ作成
mesh = create_mesh(stage, rootNode.GetPath().AppendChild('Mesh'))
# マテリアル作成
material = create_material(stage, rootNode.GetPath().AppendChild('Material'))
# シェーダー作成
shader = create_shader(stage, material.GetPath().AppendChild('PBRShader'))
# マテリアルとシェーダーの接続
material.GetSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), 'surface')
# メッシュとマテリアルのバインド
api = UsdShade.MaterialBindingAPI(mesh)
api.Apply(mesh.GetPrim()).Bind(material)
# USDファイルにエクスポート
stage.GetRootLayer().Export('./Material.usda')
出力は次のとおりになりました。usdchecker もパスしています。
#usda 1.0
(
defaultPrim = "World"
metersPerUnit = 0.01
upAxis = "Y"
)
def Xform "World"
{
def Mesh "Mesh" (
prepend apiSchemas = ["MaterialBindingAPI"]
)
{
uniform bool doubleSided = 0
int[] faceVertexCounts = [4, 4]
int[] faceVertexIndices = [0, 1, 4, 3, 1, 2, 5, 4]
rel material:binding = </World/Material>
point3f[] points = [(-1, 0, 0), (0, 0, 0), (1, 0, 0), (-1, 1, 0), (0, 1, 0), (1, 1, 0)]
texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1)] (
interpolation = "faceVarying"
)
int[] primvars:st:indices = [0, 1, 2, 3, 5, 4, 7, 6]
}
def Material "Material"
{
token inputs:frame:stPrimvarName = "st"
token outputs:surface.connect = </World/Material/PBRShader.outputs:surface>
def Shader "PBRShader"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (1, 0, 1)
float inputs:metalic = 0
float inputs:opacity = 1
float inputs:roughness = 0.4
token outputs:surface
}
}
}
$ usdchecker Material.usda
Success!
マテリアルを表示してみます。前回作成したメッシュがマテリアルの表面にバインドされました。
まとめ
マテリアルを作成して,前回作成したメッシュをこの面にバインドすることができました。次回はここに画像を貼り付けていきます。
参考資料
ft-lab (Yutaka Yoshisaka) さん,あんどうめぐみさん による以下のサイトが理解の助けになりました。