Blender 3.5 の使い方 (22) VDMブラシ

前 (ヘアカーブの進化) www.mztn.org 次 (アセットライブラリ)


Vector Displacement Mapブラシの使い方と作り方

VDMSetup-0.2.zip

Vector Displacement Map ブラシとは

次の動画を見れば、10秒で理解できると思います。 ドローブラシをドラッグする距離と方向で、スカルプトする形状の大きさと方向が決まります。ドラッグ中に [Esc] キーを押すとキャンセルできます。


Vector Displacement Map とは

メッシュの頂点を移動して、スタンプのように決まった形状を作るための仕組みです。 ハイポリメッシュに対して、スカルプトモードのドローブラシをVector Displacement Map の設定にして使います。

Vector Displacement Map の仕組みは簡単です。 次の図のように平面状のメッシュを変形させた時の、頂点の移動方向と移動量をベクトルで表した値をテクスチャ画像として保存して、ブラシに登録してメッシュを変形させます。

VectorDisplacementMap1.png


法線マップと同じように画像ファイルに保存しますが、法線ベクトルが長さ1で、面の表を向いているのに対して、Vector Displacement Map では、色々な長さで、方向も3軸それぞれで正負の値が必要となります。

各軸が 8bit の精度では不足するため、普通の画像形式ではなく色を浮動小数点数で扱うことができる OpenEXR という画像形式で保存します。 ここでは16ビットの半精度浮動小数点数を使っていますが、VDMブラシとしては十分な精度が得られます。

VDMブラシ用アドオン

VDMブラシの使い方と作り方の詳しい手順は下で説明しますが、長くて覚えてられないのでアドオンを作りました。

VDMブラシ用のテクスチャ画像6種とアドオンをまとめたものを公開します。 こちらからダウンロード (VDMSetup-0.2.zip) できます。

アドオン VDMSetup.py のソースです。

import bpy
import os
from bpy.props import StringProperty, BoolProperty
from bpy.types import Operator
from bpy_extras.io_utils import ImportHelper

# 2023-03-17
bl_info = {
   "name": "Setup VDM brush",
   "author": "Jun Mizutani",
   "version": (0, 2),
   "blender": (3, 5, 0),
   "location": "3D View",
   "description": "Change brush settings between Draw Brush and VDM brush",
   "warning": "",
   "category": "Sculpt"
}

# update checkbox
def vdm_update_callback(self, context):
    scene = context.scene
    brush = bpy.data.brushes["SculptDraw"]
    if (scene.prop_vdm == True):
        brush.stroke_method = 'ANCHORED'
        brush.curve_preset = 'CONSTANT'
        brush.texture_slot.map_mode = 'AREA_PLANE'
        brush.use_color_as_displacement = True
    else:
        brush.stroke_method = 'SPACE'
        brush.curve_preset = 'SMOOTH'
        brush.texture_slot.map_mode = 'TILED'
        brush.use_color_as_displacement = False
        brush.texture_slot.texture = None

# VDM Panel
class VDM_PT_Panel(bpy.types.Panel):
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'Tool'
    bl_label = 'VDM'

    # draw checkbox only in sculpt mode
    @classmethod
    def poll(cls, context):
        if context.mode == "SCULPT":
            if context.tool_settings.sculpt.brush.name == 'SculptDraw':
                return True
        return False

    def draw(self, context):
        scene = context.scene
        layout = self.layout
        layout.prop(scene, "prop_vdm", text="VDM Brush")
        layout.operator(VDM_OT_Button.bl_idname,text="Load VDM Image")
        layout.operator(VDM_OT_MakeButton.bl_idname,text="VDM Shader")

# [Load VDM Brush] Button
class VDM_OT_Button(bpy.types.Operator):
    bl_idname = "vdm.load"
    bl_label = "Load VDM"

    def execute(self, context):
        bpy.ops.vdm.open_filebrowser('INVOKE_DEFAULT')
        return{'FINISHED'}

# [VDM Shader] Button
class VDM_OT_MakeButton(bpy.types.Operator):
    bl_idname = "vdm.material"
    bl_label = "VDM Shader"

    def execute(self, context):
        # material
        material = bpy.data.materials.new(name="VDM_material")
        material.use_nodes = True
        node_tree = material.node_tree
        node_tree.nodes.remove(node_tree.nodes.get('Principled BSDF'))
        material_output = node_tree.nodes.get('Material Output')
        # add nodes
        tex_coord = node_tree.nodes.new('ShaderNodeTexCoord')
        multadd = node_tree.nodes.new('ShaderNodeVectorMath')
        subtract = node_tree.nodes.new('ShaderNodeVectorMath')
        teximage = node_tree.nodes.new('ShaderNodeTexImage')
        multadd.inputs[1].default_value = (2.0, 2.0, 0)
        multadd.inputs[2].default_value = (-1.0, -1.0, 0)
        # operation
        subtract.operation = 'SUBTRACT'
        multadd.operation = 'MULTIPLY_ADD'
        # location
        tex_coord.location = (00, 200)
        multadd.location = (200, 200)
        subtract.location = (400, 200)
        material_output.location = (600, 200)
        teximage.location = (400, 50)
        # links
        links = node_tree.links
        links.new(tex_coord.outputs[2], multadd.inputs[0])
        links.new(tex_coord.outputs[3], subtract.inputs[0])
        links.new(multadd.outputs[0], subtract.inputs[1])
        links.new(subtract.outputs[0],material_output.inputs[0])
        # make teximage active
        node_tree.nodes.active = teximage
        return{'FINISHED'}

# Filebrowser
class OT_VDMOpenFilebrowser(Operator, ImportHelper):
     bl_idname = "vdm.open_filebrowser"
     bl_label = "Load VDM Image"

     filter_glob: StringProperty(
         default='*.exr',
         options={'HIDDEN'} )

     def execute(self, context):
         path = self.filepath
         dir, filename = os.path.split(path)
         new_texture = bpy.data.textures.new(filename, type='IMAGE')
         new_texture.image = bpy.data.images.load(filepath=path)
         return {'FINISHED'}

def init_props():
    scene = bpy.types.Scene
    scene.prop_vdm = BoolProperty(
        name="vdm",
        description="Enable VDM Brush",
        default=False, update=vdm_update_callback
    )

def clear_props():
    scene = bpy.types.Scene
    del scene.prop_vdm

def register():
    bpy.utils.register_class(VDM_OT_Button)
    bpy.utils.register_class(VDM_OT_MakeButton)
    bpy.utils.register_class(VDM_PT_Panel)
    bpy.utils.register_class(OT_VDMOpenFilebrowser)
    init_props()

def unregister():
    clear_props()
    bpy.utils.unregister_class(VDM_PT_Panel)
    bpy.utils.unregister_class(VDM_OT_Button)
    bpy.utils.unregister_class(VDM_OT_MakeButton)
    bpy.utils.unregister_class(OT_VDMOpenFilebrowser)

if __name__ == "__main__":
    register()

アドオンのインストール

「install」をクリックして、ファイルブラウザから保存した VDMSetup.py を選択します。 「vdm」で検索して「Setup VDM Brush」にチェックを入れます。

VDMSetup01.png


アドオンの場所

インストールしたアドオンは、スカルプトモードでドローブラシを選択したときだけプロパティのアクティブツールタブの下の方とサイドバーの「Tool」タブにパネルが現れます。 このパネルは移動できるため、必要に応じて上の方の使いやすい位置に移動してください。

VDMSetup02.png


Load VDM Image

ファイルブラウザが開きます。 拡張子が「exr」のOpenEXR形式のファイルをVDMブラシとして選択します。 連続して画像を読み込んでも、別々のテクスチャとして読み込まれるため、VDMブラシのテクスチャ画像をクリックすることで選択できるようになります。

VDMSetup03.png


VDM Brush

チェックボックスをチェックして、テクスチャ画像をクリックして、使用するVDMブラシを選択します。 スカルプト対象のオブジェクト上でマウスを左ドラッグすると、サイズと方向を変更できます。

VDMSetup04.png


VDM Shader

Vector Displacement Mapを作成するためのシェーダノードを作成します。 変形後のメッシュをVDM用のテクスチャとしてマテリアルに出力するシェーダノードです。 そのマテリアルをテクスチャ画像にベイクして VDM用の画像を作成します。 「blendファイルで配布してアペンドで使う」のは面倒なので、Python スクリプトでシェーダノードを作っています。 ベイクの前に画像ファイルはイメージエディタで作成しておく必要があります。

VDMSetup05.png


VDMブラシの使い方

これ以降は上記のアドオンを使用しないで、VDMブラシを使う場合の手順です。

スカルプト用のメッシュを用意する

デフォルトキューブにVDMブラシでスカルプトすることにします。 メッシュを十分細かくするため、編集モードにします。

UseVDM_001.png


辺 (Edge) から Subdivide を選択します。

UseVDM_002.png


今回は10分割を2回行いました。

UseVDM_003.png


以上で、スカルプトの対象とする約9万頂点のオブジェクトができました。

UseVDM_004.png



ドローブラシをVDMブラシとして設定する

スカルプトモードでドローブラシを選択して、プロパティエディタからアクティブツールを選択します。 テクスチャの項目で、「New」をクリックします。

UseVDM_005.png


「New」をクリックした後で現れるアイコンをクリックするとテクスチャタブに切り替わります。

UseVDM_006.png


OpenEXR形式のファイルを読み込み

Image で「Open」をクリックして画像を読み込みます。

UseVDM_007.png


VDMブラシで使う画像は拡張子が「exr」のOpenEXR形式のファイルになります。 ここで使っている「VDM_Test.exr」の作り方は、後半で説明します。

UseVDM_Load.png


画像を読み込んだら、「Alpha」 と 「Clamp」のチェックを外します。

UseVDM_008.png


タブからアクティブツールを選択して、マッピング を「Area Plane (エリア平面)」を選択し、Vector Displacement (ベクトルディスプレイスメント) をチェックします。 ストロークは「Anchored (アンカー)」、Falloff(減衰) は 「Constant (一定)」 を選びます。

以上でVDMブラシの準備は終了です。

UseVDM_009.png


VDMブラシで描画

最初の動画のように、ドローブラシをドラッグする距離と方向で、スカルプトする形状の大きさと方向が決まります。位置を修正する場合には、ドラッグ中に [Esc] キーを押すと描画をキャンセルできるので、再度描画します。

ブラシの「強さ」は 1.0 で使いますが、小さくすると薄くなります。 またコントロールキーを押しながらマウスをドラッグすると凹凸が逆になります。 Falloff(減衰)をスムーズなどに変更すると境界が目立たなくなります。 マスクを使うとマスクの強さによって変形量が変わります。


スカルプト対象のメッシュの密度が充分でないと、VDMブラシで描画しても元の形状が再現できない場合があります。 Vector Displacement Mapの解像度より、描画対象のメッシュの密度が重要です。

UseVDM_010.png


ドローブラシへ戻す

ドローブラシを VDM ブラシに切り替える方法を説明しましたが、反対にドローブラシに戻す方法も書いておきます。 まず赤枠の[X]をクリックして、テクスチャの割当を解除します。

UseVDM_011.png


「Vector Displacement」のチェックを外して、ストローク方法を「Space」に戻します。

UseVDM_012.png


最後にフォールオフを「Smooth」に戻すと普通のドローブラシへ戻ります。

UseVDM_013.png


複数のVDMブラシを切り替えて使う

ここまでは、1つの VDM ブラシを設定して使いましたが、VDM ブラシを使う場合は複数の形状、例えば、目、耳、鼻、口などのブラシを切り替えて使いたい場合もあると思います。 ここまでの説明のように VDM の画像ファイルを読み込んでブラシに設定して描画して、次のブラシを設定して描画して、、、では面倒です。

イメージエディタに画像ファイルを連続して読み込んで、VDM ブラシでテクスチャを切り替えて使うことができます。

イメージエディタに読み込んでフェイクユーザを設定する

画像ファイルをフェイクユーザを設定すると、保存して再度開いた場合に削除されることがなくなります。 ファイル/外部データ/リソースの自動パック (File/External Data/Automatically Pack resources) をチェックすると blend ファイルに残すこともできます。

UseVDM_face0.png


テクスチャにVDM用画像を登録

プロパティのテクスチャタブでテクスチャと画像ファイルを関連付けます。


テクスチャを登録して名前をつける

読み込んだ画像ファイルをテクスチャに設定してテクスチャ名をつけます。

UseVDM_face1.png


VDMブラシにテクスチャを設定

テクスチャのドロップダウンで指定したテクスチャをブラシに設定できます。

UseVDM_face2.png


ブラシのテクスチャを選択

テクスチャの画像をクリックしてもテクスチャを選択できます。 こちらの方法が楽です。

UseVDM_face3.png


VDMブラシを使う

ブラシをドラッグ開始した位置が中心となって、移動する距離と方向で、スカルプトする形状の大きさと方向が決まります。

UseVDM_face4.png



VDMブラシを作る

Vector Displacement Mapの仕組み

VDM ブラシの形状を作成

VDM ブラシの形状をスカルプトするための平面を用意します。Z座標が0でXY座標が±1の範囲の平面のメッシュですが、Blenderを起動して立方体を削除して、平面(Plane)を追加するだけです。

MakeVDM_000.png


VDM ブラシが生成する形状を平面のメッシュをスカルプトして作りますが、メッシュを十分に細かくしておきます。

MakeVDM_001.png


編集モードで、辺(Edge)メニューからサブディバイドを選択します。 ここでは 10回を2度行いました。 ポリゴン数が多くても最終的なVDM ブラシには影響しません。

MakeVDM_002.png


大きく変形するとポリゴンが伸び過ぎたりするため、ワイヤーフレーム表示にすると確認しやすくなります。

MakeVDM_003.png


Vector Displacement Map作成用のシェーダノードの設定

Vector Displacement Mapを作成するためのシェーダノードを設定しますが、3種類だけなので簡単です。

まず、シェーダエディターを表示して、「New」をクリックします。

MakeVDM_004A.png


「Material Output」を残し、「Principled BSDF」を選択して、[X] か [Delete] キーで削除します。

MakeVDM_004B.png


Add メニューから「Input / Texture Coordinate」、「Converter / Vector Math」を2つ、「Texture / Image Texture」ノードを追加します。

MakeVDM_005.png


「Vector Math」ノードの「Add」のドロップダウンリストから「Multiply Add」を選択します。右側の「Add」は「Subtract」に変更します。

テクスチャ座標の「UV」を「Multiply Add」に接続して、XとY成分を2倍して1を減算します。 これで、UV座標とメッシュ平面上の座標が一致します。Z成分は0になるようにします。 テクスチャ座標の「Object」から「Multiply Add」の出力の Vector を減算(Subtract) すると 「Vector Displacement」が求められます。これをマテリアル出力に接続するだけです。 ベイクの出力用のテクスチャをアクティブにするため、Image Texture ノードを選択しておきます。

MakeVDM_006.png


画像エディタで「New」を押してベイク結果の書き込み先のテクスチャ画像を作成します。

MakeVDM_007.png


ここでは「VDM_test」をいう名前にして、256 x 256 の画像を生成します。メッシュの解像度が120程度なので、128 x 128 ピクセルでも十分ですが、400KB程度の画像なので 1辺 256ピクセルの画像としています。

MakeVDM_008.png


ベイクするために、レンダーエンジンは「Cycles」にします。

MakeVDM_009.png


デノイズは不要なのでチェックを外します。

MakeVDM_010.png


ベイクタイプは「Emit (放射)」にして、ビュー元は「Above Surface (表面の上)」に設定します。


MakeVDM_011.png


メッシュをスカルプトします。 高さマップではないので、曲がった形状でも大丈夫です。 ただし、メッシュが引き伸ばされる場合でもリメッシュは使えません。 元の平面のUV座標と形が変化したメッシュ頂点の対応が崩れてしまうためです。

MakeVDM_012.png


変形が大きいと「スライドリラックス」ブラシを使ったり、編集モードで頂点を移動したりしてメッシュの形状を整える必要があります。

MakeVDM_013.png


オブジェクトモードで、「Bake (ベイク)」を押すと、画像が生成されます。頂点が移動したところに色が付きますが、各軸のマイナス方向の移動は黒のままです。

MakeVDM_014.png


VDMブラシ用の画像を保存します。

MakeVDM_015.png


保管する画像のフォーマットは「OpenEXR」とします。 色は「RGB」、色深度は「Float(Half)」とします。 16ビットの半精度浮動小数点数ですが、ベクトルマップとしての数値の精度は十分です。

MakeVDM_017.png


描画時の歪み

もし、VDMブラシで描画する場合に歪みが生ずる場合は、VDMブラシの画素の要素が 0.0 から 1.0 にクリップされた状態の可能性があります。 平面上の移動ベクトルも正方向のみとなるのでVDMブラシの形が歪むことになります。

UseVDM_010_BadVDM.png


通常の画像ファイルと異なって、VDMブラシの色要素は浮動小数点数で格納されるため、負の値や1.0以上の値となる可能性があります。 Vector Displacement Map では負の値が格納されているのが普通です。


OpenEXRファイルの画素の値を確認する方法

VDMブラシの画素の要素が 0.0 から 1.0 にクリップされているかどうかは、OpenEXRの画像ファイルを調べるとわかります。

OpenEXR の画素の値は、例えばGIMP で確認する事ができます。 メニューの「Windows / Dockable Dialogs / Pointer」(「ウィンドウ/ドッキング可能なダイアログ / ピクセル情報」) をクリックして、ピクセルの色情報を表示できるようにします。

EXR_GIMP1.png


画像中のピクセルの位置によって、負の値や1より大きい値が確認できるはずです。

EXR_GIMP2.png


ページ先頭へ


Blender 2.8 - 4.1 の使い方 [目次]

copyright (C) 2019-2024 Jun Mizutani