Skip to content

第4.3章: マテリアル (.rvmat)

ホーム | << 前: 3Dモデル | マテリアル | 次: オーディオ >>


はじめに

DayZにおけるマテリアルは、3Dモデルとその視覚的な外観を橋渡しするものです。テクスチャが生の画像データを提供する一方で、RVMAT(Real Virtuality Material)ファイルはそれらのテクスチャがどのように組み合わされるか、どのシェーダーがそれらを解釈するか、そしてエンジンがシミュレートすべきサーフェスプロパティ -- 光沢、透明度、自己発光など -- を定義します。ゲーム内のすべてのP3DモデルのすべてのフェースがRVMATファイルを参照しており、それらを作成・設定する方法を理解することは、あらゆるビジュアルモッドに不可欠です。

この章では、RVMATファイルフォーマット、シェーダータイプ、テクスチャステージの設定、マテリアルプロパティ、ダメージレベルのマテリアルスワップシステム、そしてDayZ-Samplesからの実践的な例について説明します。


目次


RVMATフォーマットの概要

RVMATファイルは、マテリアルを定義するテキストベースの設定ファイル(バイナリではない)です。カスタム拡張子にもかかわらず、フォーマットはBohemiaの設定スタイルの構文を使用するプレーンテキストで、クラスとキーバリューペアで構成されています。

主な特徴

  • テキストフォーマット: 任意のテキストエディタ(Notepad++、VS Code)で編集可能です。
  • シェーダーバインディング: 各RVMATは使用するレンダリングシェーダーを指定します。
  • テクスチャマッピング: どのテクスチャファイルがどのシェーダー入力(ディフューズ、ノーマル、スペキュラなど)に割り当てられるかを定義します。
  • サーフェスプロパティ: スペキュラ強度、エミッシブグロー、透明度などを制御します。
  • P3Dモデルから参照: Object BuilderのResolution LODのフェースにRVMATが割り当てられます。エンジンはRVMATとそれが参照するすべてのテクスチャをロードします。
  • config.cppから参照: hiddenSelectionsMaterials[]はランタイムにマテリアルをオーバーライドできます。

パス規則

RVMATファイルはテクスチャと一緒に、通常はdata/ディレクトリに配置されます:

MyMod/
  data/
    my_item.rvmat              <-- マテリアル定義
    my_item_co.paa             <-- ディフューズテクスチャ(RVMATから参照)
    my_item_nohq.paa           <-- ノーマルマップ(RVMATから参照)
    my_item_smdi.paa           <-- スペキュラマップ(RVMATから参照)

ファイル構造

RVMATファイルには一貫した構造があります。以下は完全な注釈付きの例です:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};        // アンビエントカラー乗数(RGBA)
diffuse[] = {1.0, 1.0, 1.0, 1.0};        // ディフューズカラー乗数(RGBA)
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};  // 加算ディフューズオーバーライド
emmisive[] = {0.0, 0.0, 0.0, 0.0};       // エミッシブ(自己発光)カラー
specular[] = {0.7, 0.7, 0.7, 1.0};       // スペキュラハイライトカラー
specularPower = 80;                        // スペキュラの鮮明さ(高い = タイトなハイライト)
PixelShaderID = "Super";                   // 使用するシェーダープログラム
VertexShaderID = "Super";                  // 頂点シェーダープログラム

class Stage1                               // テクスチャステージ: ノーマルマップ
{
    texture = "MyMod\data\my_item_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2                               // テクスチャステージ: ディフューズ/カラーマップ
{
    texture = "MyMod\data\my_item_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3                               // テクスチャステージ: スペキュラ/メタリックマップ
{
    texture = "MyMod\data\my_item_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

トップレベルプロパティ

これらはStageクラスの前に宣言され、マテリアルの全体的な動作を制御します:

プロパティタイプ説明
ambient[]float[4]アンビエントライトカラー乗数。{1,1,1,1} = フル、{0,0,0,0} = アンビエントなし。
diffuse[]float[4]ディフューズライトカラー乗数。通常{1,1,1,1}
forcedDiffuse[]float[4]ディフューズへの加算オーバーライド。通常{0,0,0,0}
emmisive[]float[4]自己発光カラー。ゼロでない値はサーフェスを光らせます。注意: Bohemiaはemissiveではなくemmisiveというスペルミスを使用しています。
specular[]float[4]スペキュラハイライトのカラーと強度。
specularPowerfloatスペキュラハイライトの鮮明さ。範囲1-200。高い = タイトで集中した反射。
PixelShaderIDstringピクセルシェーダープログラム名。
VertexShaderIDstring頂点シェーダープログラム名。

シェーダータイプ

PixelShaderIDVertexShaderIDの値は、マテリアルを処理するレンダリングパイプラインを決定します。通常、両方を同じ値に設定する必要があります。

利用可能なシェーダー

シェーダー用途必要なテクスチャステージ
Super標準的な不透明サーフェス(武器、衣服、アイテム)ノーマル、ディフューズ、スペキュラ/メタリック
Multiマルチレイヤーの地形と複雑なサーフェス複数のディフューズ/ノーマルペア
Glass透明および半透明サーフェスアルファ付きディフューズ
Water反射と屈折を持つ水面特殊な水テクスチャ
Terrain地形の地面サーフェスサテライト、マスク、マテリアルレイヤー
NormalMap簡略化されたノーマルマップサーフェスノーマル、ディフューズ
NormalMapSpecularスペキュラ付きノーマルマップノーマル、ディフューズ、スペキュラ
Hairキャラクターの髪のレンダリングアルファ付きディフューズ、特殊なトランスルーセンシー
Skinサブサーフェススキャッタリングを持つキャラクターの肌ディフューズ、ノーマル、スペキュラ
AlphaTestハードエッジ透明度(植物、フェンス)アルファ付きディフューズ
AlphaBlendスムーズ透明度(ガラス、煙)アルファ付きディフューズ

Superシェーダー(最も一般的)

Superシェーダーは、DayZの大多数のアイテムに使用される標準的な物理ベースレンダリングシェーダーです。3つのテクスチャステージを期待します:

Stage1 = ノーマルマップ (_nohq)
Stage2 = ディフューズ/カラーマップ (_co)
Stage3 = スペキュラ/メタリックマップ (_smdi)

モッドアイテム(武器、衣服、ツール、コンテナ)を作成する場合、ほぼ常にSuperシェーダーを使用します。

Glassシェーダー

Glassシェーダーは透明サーフェスを処理します。ディフューズテクスチャからアルファを読み取って透明度を決定します:

cpp
PixelShaderID = "Glass";
VertexShaderID = "Glass";

class Stage1
{
    texture = "MyMod\data\glass_nohq.paa";
    uvSource = "tex";
    class uvTransform { /* ... */ };
};

class Stage2
{
    texture = "MyMod\data\glass_ca.paa";    // 注意: カラー+アルファ用の_caサフィックス
    uvSource = "tex";
    class uvTransform { /* ... */ };
};

テクスチャステージ

RVMAT内の各Stageクラスは、テクスチャを特定のシェーダー入力に割り当てます。ステージ番号がテクスチャの役割を決定します。

Superシェーダーのステージ割り当て

ステージテクスチャの役割一般的なサフィックス説明
Stage1ノーマルマップ_nohqサーフェスのディテール、バンプ、溝
Stage2ディフューズ/カラーマップ_coまたは_caサーフェスのベースカラー
Stage3スペキュラ/メタリックマップ_smdi光沢、メタリック特性、ディテール
Stage4アンビエントシャドウ_asプリベイクされたアンビエントオクルージョン(オプション)
Stage5マクロマップ_mc大規模な色のバリエーション(オプション)
Stage6ディテールマップ_deタイリングマイクロディテール(オプション)
Stage7エミッシブ/ライトマップ_li自己発光(オプション)

ステージプロパティ

各ステージには以下が含まれます:

cpp
class Stage1
{
    texture = "path\to\texture.paa";    // P:ドライブに対する相対パス
    uvSource = "tex";                    // UVソース: "tex"(モデルUV)または"tex1"(2番目のUVセット)
    class uvTransform                    // UV変換マトリクス
    {
        aside[] = {1.0, 0.0, 0.0};     // U軸のスケールと方向
        up[] = {0.0, 1.0, 0.0};        // V軸のスケールと方向
        dir[] = {0.0, 0.0, 0.0};       // 通常使用されない
        pos[] = {0.0, 0.0, 0.0};       // UVオフセット(移動)
    };
};

タイリング用UV変換

テクスチャをタイリング(サーフェス全体に繰り返す)するには、asideupの値を変更します:

cpp
class uvTransform
{
    aside[] = {4.0, 0.0, 0.0};     // 水平方向に4倍タイリング
    up[] = {0.0, 4.0, 0.0};        // 垂直方向に4倍タイリング
    dir[] = {0.0, 0.0, 0.0};
    pos[] = {0.0, 0.0, 0.0};
};

これは地形マテリアルや建物のサーフェスで、同じディテールテクスチャが繰り返される場合によく使用されます。


マテリアルプロパティ

スペキュラ制御

specular[]specularPowerの値が連携して、サーフェスの光沢の外観を定義します:

マテリアルタイプspecular[]specularPower外観
マットプラスチック{0.1, 0.1, 0.1, 1.0}10鈍い、広いハイライト
使い古した金属{0.3, 0.3, 0.3, 1.0}40中程度の光沢
磨かれた金属{0.8, 0.8, 0.8, 1.0}120明るく、タイトなハイライト
クロム{1.0, 1.0, 1.0, 1.0}200鏡のような反射
ゴム{0.02, 0.02, 0.02, 1.0}5ほぼハイライトなし
濡れたサーフェス{0.6, 0.6, 0.6, 1.0}80滑らかで、中程度のシャープなハイライト

エミッシブ(自己発光)

サーフェスを光らせるには(LEDライト、スクリーン、光る要素):

cpp
emmisive[] = {0.2, 0.8, 0.2, 1.0};   // 緑の発光

エミッシブカラーはライティングに関係なく最終ピクセルカラーに加算されます。後のテクスチャステージの_liエミッシブマップで、サーフェスのどの部分が光るかをマスクできます。

両面レンダリング

両側から見える薄いサーフェス(旗、植物、布)の場合:

cpp
renderFlags[] = {"noZWrite", "noAlpha", "twoSided"};

これはトップレベルのRVMATプロパティではなく、使用ケースに応じてconfig.cppまたはマテリアルのシェーダー設定を通じて構成されます。


ヘルスレベル(ダメージマテリアルスワップ)

DayZのアイテムは時間とともに劣化します。エンジンは異なるダメージしきい値での自動マテリアルスワップをサポートしており、config.cpphealthLevels[]配列で定義されます。これにより、新品から破損までの視覚的な進行が作成されます。

healthLevels[]構造

cpp
class MyItem: Inventory_Base
{
    // ... その他の設定 ...

    healthLevels[] =
    {
        // {ヘルスしきい値, {"マテリアルセット"}},

        {1.0, {"MyMod\data\my_item.rvmat"}},           // 新品(100%ヘルス)
        {0.7, {"MyMod\data\my_item_worn.rvmat"}},       // 使い古し(70%ヘルス)
        {0.5, {"MyMod\data\my_item_damaged.rvmat"}},     // 損傷(50%ヘルス)
        {0.3, {"MyMod\data\my_item_badly_damaged.rvmat"}},// ひどく損傷(30%ヘルス)
        {0.0, {"MyMod\data\my_item_ruined.rvmat"}}       // 破損(0%ヘルス)
    };
};

仕組み

  1. エンジンがアイテムのヘルス値(0.0〜1.0)を監視します。
  2. ヘルスがしきい値を下回ると、エンジンは対応するRVMATにマテリアルをスワップします。
  3. 各RVMATは異なるテクスチャを参照できます -- 通常、段階的に損傷した外観のバリアントです。
  4. スワップは自動的です。スクリプトコードは不要です。

ダメージテクスチャの進行

一般的なダメージ進行:

レベルヘルス視覚的変化
新品1.0きれいな、工場出荷時の外観
使い古し0.7わずかな擦り傷、軽微な傷
損傷0.5目に見える傷、変色、汚れ
ひどく損傷0.3重度の摩耗、錆、亀裂、塗装剥がれ
破損0.0ひどく劣化した、壊れた外観

ダメージマテリアルの作成

各ダメージレベルに対して、段階的に損傷したテクスチャを参照する個別のRVMATを作成します:

data/
  my_item.rvmat                    --> my_item_co.paa(きれい)
  my_item_worn.rvmat               --> my_item_worn_co.paa(軽微なダメージ)
  my_item_damaged.rvmat            --> my_item_damaged_co.paa(中程度のダメージ)
  my_item_badly_damaged.rvmat      --> my_item_badly_damaged_co.paa(重度のダメージ)
  my_item_ruined.rvmat             --> my_item_ruined_co.paa(破壊)

ヒント: すべてのダメージレベルに固有のテクスチャが必要とは限りません。一般的な最適化は、ノーマルマップとスペキュラマップをすべてのレベルで共有し、ディフューズテクスチャのみを変更することです:

my_item.rvmat           --> my_item_co.paa
my_item_worn.rvmat      --> my_item_co.paa(同じディフューズ、低いスペキュラ)
my_item_damaged.rvmat   --> my_item_damaged_co.paa
my_item_ruined.rvmat    --> my_item_ruined_co.paa

バニラダメージマテリアルの使用

DayZは、カスタムダメージテクスチャを作成したくない場合に使用できる汎用ダメージオーバーレイマテリアルのセットを提供しています:

cpp
healthLevels[] =
{
    {1.0, {"MyMod\data\my_item.rvmat"}},
    {0.7, {"DZ\data\data\default_worn.rvmat"}},
    {0.5, {"DZ\data\data\default_damaged.rvmat"}},
    {0.3, {"DZ\data\data\default_badly_damaged.rvmat"}},
    {0.0, {"DZ\data\data\default_ruined.rvmat"}}
};

マテリアルがテクスチャを参照する方法

モデル、マテリアル、テクスチャ間の接続はチェーンを形成します:

P3Dモデル(Object Builder)
  |
  |--> フェースにRVMATを割り当て
         |
         |--> Stage1.texture = "path\to\normal_nohq.paa"
         |--> Stage2.texture = "path\to\color_co.paa"
         |--> Stage3.texture = "path\to\specular_smdi.paa"

パス解決

RVMATファイル内のすべてのテクスチャパスはP:ドライブルートに対する相対パスです:

cpp
// 正しい: P:ドライブに対する相対パス
texture = "MyMod\data\textures\my_item_co.paa";

// これは次を意味します: P:\MyMod\data\textures\my_item_co.paa

PBOにパックする場合、パスプレフィックスはPBOのプレフィックスと一致する必要があります:

PBOプレフィックス: MyMod
内部パス: data\textures\my_item_co.paa
完全参照: MyMod\data\textures\my_item_co.paa

hiddenSelectionsMaterialsオーバーライド

Config.cppはランタイムに名前付きセレクションに適用されるマテリアルをオーバーライドできます:

cpp
class MyItem_Green: MyItem
{
    hiddenSelections[] = {"camo"};
    hiddenSelectionsTextures[] = {"MyMod\data\my_item_green_co.paa"};
    hiddenSelectionsMaterials[] = {"MyMod\data\my_item_green.rvmat"};
};

これにより、同じP3Dモデルを共有しながら異なるマテリアルを使用するアイテムバリアント(カラースキーム、カモパターン)を作成できます。


RVMATをゼロから作成する

ステップバイステップ: 標準不透明アイテム

  1. テクスチャファイルを作成します:

    • my_item_co.paa(ディフューズカラー)
    • my_item_nohq.paa(ノーマルマップ)
    • my_item_smdi.paa(スペキュラ/メタリック)
  2. RVMATファイルを作成します(プレーンテキスト):

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.5, 0.5, 0.5, 1.0};
specularPower = 60;
PixelShaderID = "Super";
VertexShaderID = "Super";

class Stage1
{
    texture = "MyMod\data\my_item_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2
{
    texture = "MyMod\data\my_item_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3
{
    texture = "MyMod\data\my_item_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};
  1. Object Builderで割り当てます:

    • P3Dモデルを開きます。
    • Resolution LODでフェースを選択します。
    • 右クリック --> Face Properties
    • RVMATファイルを参照します。
  2. ファイルパッチングまたはPBOビルドでゲーム内でテストします。


実際の例

DayZ-Samples Test_ClothingRetexture

公式DayZ-Samplesには、標準的なマテリアルワークフローを示すTest_ClothingRetextureの例が含まれています:

cpp
// DayZ-Samplesリテクスチャの例から
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.3, 0.3, 0.3, 1.0};
specularPower = 50;
PixelShaderID = "Super";
VertexShaderID = "Super";

class Stage1
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_nohq.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage2
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_co.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

class Stage3
{
    texture = "DZ_Samples\Test_ClothingRetexture\data\tshirt_smdi.paa";
    uvSource = "tex";
    class uvTransform
    {
        aside[] = {1.0, 0.0, 0.0};
        up[] = {0.0, 1.0, 0.0};
        dir[] = {0.0, 0.0, 0.0};
        pos[] = {0.0, 0.0, 0.0};
    };
};

メタリック武器マテリアル

高いメタリックレスポンスを持つ磨かれた武器バレル:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.0, 0.0, 0.0, 0.0};
specular[] = {0.9, 0.9, 0.9, 1.0};        // 金属用の高スペキュラ
specularPower = 150;                        // タイトで集中したハイライト
PixelShaderID = "Super";
VertexShaderID = "Super";

// ... 武器テクスチャを使用したStage定義 ...

エミッシブマテリアル(光るスクリーン)

光を発するデバイススクリーン用のマテリアル:

cpp
ambient[] = {1.0, 1.0, 1.0, 1.0};
diffuse[] = {1.0, 1.0, 1.0, 1.0};
forcedDiffuse[] = {0.0, 0.0, 0.0, 0.0};
emmisive[] = {0.05, 0.3, 0.05, 1.0};      // 柔らかい緑の発光
specular[] = {0.5, 0.5, 0.5, 1.0};
specularPower = 80;
PixelShaderID = "Super";
VertexShaderID = "Super";

// ... Stage7に_liエミッシブマップを含むStage定義 ...

よくある間違い

1. ステージの順序の誤り

症状: テクスチャがスクランブルされて表示され、ノーマルマップがカラーとして表示され、カラーがバンプとして表示される。 修正: Superシェーダーの場合、Stage1 = ノーマル、Stage2 = ディフューズ、Stage3 = スペキュラであることを確認してください。

2. emmisiveのスペルミス

症状: エミッシブが動作しない。 修正: Bohemiaはemmisive(ダブルm、シングルs)を使用しています。正しい英語のスペルemissiveを使用しても動作しません。これは既知の歴史的な癖です。

3. テクスチャパスの不一致

症状: モデルがデフォルトのグレーまたはマゼンタのマテリアルで表示される。 修正: RVMAT内のテクスチャパスがP:ドライブに対する相対的なファイル位置と正確に一致していることを確認してください。パスにはバックスラッシュを使用します。大文字小文字を確認してください -- 一部のシステムでは大文字小文字が区別されます。

4. P3Dでのrvmat割り当ての欠落

症状: モデルがマテリアルなしでレンダリングされる(フラットグレーまたはデフォルトシェーダー)。 修正: Object Builderでモデルを開き、フェースを選択し、Face PropertiesでRVMATを割り当ててください。

5. 透明アイテムに間違ったシェーダーを使用

症状: 透明テクスチャが不透明に見える、またはサーフェス全体が消える。 修正: 透明サーフェスにはSuperの代わりにGlassAlphaTest、またはAlphaBlendシェーダーを使用してください。適切なアルファチャンネルを持つ_caサフィックスのテクスチャを使用してください。


ベストプラクティス

  1. 動作する例から始めてください。 DayZ-Samplesまたはバニラアイテムからrvmatをコピーして変更してください。ゼロから始めるとタイプミスが発生しやすくなります。

  2. マテリアルとテクスチャを一緒に保管してください。 テクスチャと同じdata/ディレクトリにRVMATを保存してください。関係が明確になり、パス管理が簡素化されます。

  3. 理由がない限りSuperシェーダーを使用してください。 95%のユースケースを正しく処理します。

  4. シンプルなアイテムでもダメージマテリアルを作成してください。 アイテムが視覚的に劣化しないとプレイヤーは気づきます。最低限、低いヘルスレベルにはバニラのデフォルトダメージマテリアルを使用してください。

  5. スペキュラはObject Builderではなくゲーム内でテストしてください。 エディタのライティングとゲーム内のライティングは非常に異なる結果を生み出します。Object Builderで完璧に見えるものが、DayZのダイナミックライティングの下では光りすぎたり鈍すぎたりする可能性があります。

  6. マテリアル設定を文書化してください。 サーフェスタイプに適したスペキュラ/パワー値を見つけたら記録してください。これらの設定は多くのアイテムで再利用します。


ナビゲーション

4.2 3DモデルPart 4: ファイルフォーマット & DayZ Tools4.4 オーディオ

Released under CC BY-SA 4.0 | Code examples under MIT License