2020年5月20日水曜日

C++ Templates - The Complete Guide, 2nd 読書メモ 2章 クラステンプレート

C++ Templates - The Complete Guide, 2ndの2章「クラステンプレート」の読書メモ

スタックの実装を例にクラステンプレートについて解説している.


クラステンプレートの宣言


関数テンプレートと同様に,templateの後にテンプレート仮引数を並べ,クラス宣言を書く.

template <typename T>
class Stack {
  ...
};

クラステンプレート内では,Tを型として利用できる.

コピーコンストラクタなどを書く場合,次の2通りの書き方があるが,敢えて書くと意味があるように思わせるので,前者の方が良い.

Stack(const Stack &);
Stack(const Stack<T> &);

メンバ関数の実装


クラステンプレートのメンバ関数を実装する方法として,クラスの外側で定義する方法とクラス内で定義する方法が紹介されている.

ついでに,例外安全についても触れていて,Exceptional C++が紹介されている.

クラステンプレートの利用


基本的には,クラステンプレートを利用する場合は型を明示する必要があるが,C++17では型を省略する方法が追加され,後ほど解説する,とある.

また,呼び出されたテンプレート(メンバ)関数のみがインスタンス化される,とある.

friend


フレンド関数を定義するには,クラス内で宣言してしまう方法と,後から別途宣言する方法が2つ紹介されている.

template <typename U>
friend std::ostream & operator<<(std::ostream &, const Stack<U> &); // 別途非メンバ関数として定義する

template <typename T>
class Stack; // 前方宣言
template <typename T>
std::ostream & operator<<(std::ostream &, const Stack<T> &);

template <typename T>
class Stack {
    friend std::ostream & operator<< <T>(std::ostream &, const Stack<T> &);
};

テンプレートの特殊化


template <>として,クラス名の後に具体的な型を指定して定義することで,特定の型の場合について専用の実装を用意することができる.

例としては,std::vector<bool>など.

例えば,typename Tに対して,T *,とポインタ型にするような部分的な特殊化も可能.

デフォルト実引数


関数テンプレートと同様に,テンプレート仮引数にデフォルト実引数を指定することが可能.

タイプエイリアス


typedefのように型の別名を定義する方法として,usingによるエイリアス宣言が紹介されている.

typedefよりも = でつなぐ分,読みやすい,とも.

また,エイリアスはテンプレートにもできる.

template <typename T>
using DequeStack = Stack<T, std::deque<T>>;

C++14以降では,標準ライブラリでは 型とレイトである型から他の型を取り出す場合,今まではA::typeとしていたのを,A_tというようなエイリアスが用意された.

クラステンプレート実引数推論


C++17から,初期化時の実引数からクラステンプレートの型を推論できるようになった.使い方次第では便利なのだろうけれど,使いこなせない気がする.

文字列を利用して推論する場合の注意点についても触れている.コンストラクタが参照を受け取るようになっていると,文字列から推論しようとするとconst char [x]のような型になってしまうが,値渡しにしていると,const char *になる.

推論ガイド(deduction guide)についてもサラッと触れている.

テンプレート化された集成体


ユーザー定義または継承したコンストラクタを持たず,privateやprotectedな非staticメンバを持たず,仮想関数,仮想またはprivateまたはprotectedなベースクラスを持たないクラスまたは構造体をテンプレートにすることもできる.

2020年5月7日木曜日

C++ Templates - The Complete Guide, 2nd 読書メモ 1章 関数テンプレート

C++ Templates - The Complete Guide, 2ndの1章「関数テンプレート」の読書メモ

関数テンプレートとは

int max(int, int);
double max(double, double);
string max(string, string);

このように,型が違うだけで同じような関数をまとめて,次のように型名をtypenameで仮引数として定義できる.

template <typename T>
T max(T, T);

family of functions,という表現がポイントなのかな,と.

この関数テンプレートは,次のように呼び出せる.

max(1, 3);
max(1.0, 3.0);

このとき,具体的にTにintやdoulbeがあてはめられて関数が生成される.具体的な関数が生成されることをインスタンス化(instantiation)と呼び,生成された関数をテンプレートのインスタンス(instance)と呼ぶ.

Two-Phase Translation

テンプレートは,定義をしたタイミングと,具体的な型が割り当てられたタイミングの2つのタイミングで解釈が行われる.例えば,上記のmaxであれば大小比較が必要なので,大小比較が定義されていない型が渡されると,インスタンス化のタイミングでエラーとなる.

一方で,テンプレートの定義時点で定義されていない型名が関数テンプレート内で利用されている,といった文法上のエラーなどがある場合に,仕様上はエラー判定が行われるのだけれど,Microsoft Visual C++はその辺が緩い.Clangだとちゃんとエラーになる.その辺の挙動を切り替える方法については,次のリンク先にまとめてある.


型推論時の型変換

関数テンプレートは,呼び出し時に渡された実引数から型を自動的に決定する.これを型推論(Type Deduction)と言う.

この型推論が行われる際には,型変換が制限される.例えば,doubleを受け取る関数にintの値を渡しても,普段であれば暗黙の型変換が行われるが,関数テンプレートの場合,エラーになる.
max(1, 3.0); // コンパイルエラー

これを回避するには,明示的にキャストをするか,関数テンプレートの型を直接していする.

max(1, 3.0); // T=doubleとして判定される.

ちなみに,必要性が分からないのだけれど,デフォルト実引数を指定していたとしても,デフォルト実引数の型をもとに型推論は行われない,とのこと.

複数のテンプレート仮引数


標準ライブラリのmaxはそうなっていないけれど,説明のためにmaxのテンプレート仮引数を複数にして,複数の型を受け取れるようにしよう,という説明が進む.

こうすると,今度は返り値の型はどちらにそろえるんだ,といった問題が発生する.

そこで,返り値の型を推論する方法が示される.(書籍よりコードを抜粋)

template <typename T1, typename T2>
auto max(T1 a, T2 b) -> std::decay_t<decltype(true ? a : b)>
{
    return b < a ? a : b;
}

返り値の型を指定するところにautoを書いて,後ろにアロー(->)を書いて,decltypeで式の結果の型を求める.結果が参照などでは困る場合があるので,std::decay_tを利用して返り値の型に適切な型に変換する.

次のように,std::common_type_tを利用する方法も示されている.

template <typename T1, typename T2>
std::common_type_t max(T1 a, T2 b)
{
    return b < a ? a : b;
}

あくまでも説明のために出しているだけで,実際にこれをやると,intとdouble,doubleとint,のように型がひっくり返っているだけでも別の関数が生成されてしまい,プログラムサイズが無駄に増えるので望ましくないと思われる.

ちなみに,a > bとしないのは,C++の仕様を見るに,基本的には < を基準に比較演算が考えられているからだと思われる.

デフォルトテンプレート実引数


通常の関数と同様に,テンプレート仮引数にもデフォルト実引数を指定することができる.ただし,関数テンプレートにデフォルトテンプレート実引数を指定できるようになったのは,C++11以降なので注意が……今時必要ない気がするけど,未だにC++11さえも使えない環境もあるかもしれない.そうだとすると相当ツライ……

関数テンプレートのオーバーロード


通常の関数と同様に,関数テンプレートもオーバーロードできる.これ,意外と驚かれる.通常の関数もオーバーロードに含めた場合,どちらが優先されるかなどについては,13章で詳しく扱うようだ.第一版では9章だったので,4章ほど追加されているのかな.

その他


この単純なmax関数だけでも,色々考えることがあって,値渡しと参照渡し,どちらが良いのか,inlineにはできないのか,constexprは,など色々考えることがあるよ,と.

2020年5月6日水曜日

MSVCとClangにおけるテンプレートの名前の解釈の切り替え

Clangのドキュメントによると,Microsoft Visual C++では,テンプレートがインスタンス化されるまでインラインメソッドの本体の解析が行われないが,clangは行う.これだと,Windows系のヘッダファイルの解析時に問題になるので,-fdelayed-template-parsing,というオプションを指定することで,VC++と同じ挙動に出来る.

つまり,次のようなコードのコンパイルが通るようになってしまう.

template  void f(Type t) {
    Typo t; // 敢えてタイプミス
}

int main()
{
    // fのインスタンス化はしていない
}


一方で,VC++をClangと同じようにする方法がある.プロジェクト設定のC/C++の言語から,準拠モードを「はい(/permissive-)」にすれば良い.

詳細についてはC++ Team Blogで紹介されている.

MS Docsによれば,Visual Studio 2017 15.5以降ではデフォルトでこの設定が「はい」になるとのこと.逆に言えば,それより前から継続して使っているプロジェクトには設定されていないということなので,何かのきっかけで新しいプロジェクトを追加した際などには,この設定の差が問題になるかもしれない.

2020年3月17日火曜日

Android/iOS向けのC/C++ライブラリをビルドするときにCMakeで引っ掛かった話

iOS/Androidの両方でOSSのライブラリを使いたい.そして,CMakeLists.txtはなるべく共通にしたい,と思って弄っていてハマったことのメモ.

プラットフォームの区別でハマる


プラットフォームでフォルダを区別するために,フォルダ名を設定する処理を次のように書いてました.

if(APPLE)
  set(PLATFORM_NAME "iOS")
elseif(ANDROID)
  set(PLATFORM_NAME "Android")
endif()

project(library)

でも,上手くいかないので何故かと思いきや,projectの後に書かないといけなかったんですね.

project(library)

if(APPLE)
  set(PLATFORM_NAME "iOS")
elseif(ANDROID)
  set(PLATFORM_NAME "Android")
endif()

iOSのビルド設定でハマる


iOS向けのビルドをするために,CMAKE_OSX系の変数をsetする場合,projectより先に書かないといけない.ドキュメントにはちゃんと書いていました.適当に拾ってきたものを利用してちゃんと調べないとダメですね.

iOS向けのCheckIncludeFile


使う場合,CMAKE_TRY_COMPILE_TARGET_TYPEをSTATIC_LIBRARYにしておかないとダメなようです.

オブジェクトライブラリでハマる


ドキュメントでも名指しされていますが,Xcodeはオブジェクトライブラリだけを利用して,そこからstaticライブラリとsharedライブラリを作る,ということができません.

iOS/Androidの両方で使える記述にしようと思うと,ソースコードは変数にまとめるしかなさそうです.ちなみに,自分の場合はstaticライブラリだけで良かったので,add_libraryに直接書きました.

インストールでハマる


特定の名前で特定のフォルダに出力されるようにしようと思ったんです.で,installコマンドで良いか,と思ったんですが,Xcodeで上手くいかない.おそらく使い方の問題だとは思うのですが,色々と面倒になったところで,楽な方法を見つけました.

set_target_properties(
  library
  PROPERTIES
  ARCHIVE_OUTPUT_DIRECTORY_DEBUG lib/${PLATFORM_NAME}/Debug
  ARCHIVE_OUTPUT_DIRECTORY_RELEASE lib/${PLATFORM_NAME}/Release
  ARCHIVE_OUTPUT_NAME_DEBUG library_debug
  ARCHIVE_OUTPUT_NAME_RELEASE library_release
)

出力ディレクトリ(ARCHIVE_OUTPUT_DIRECTORY)と出力名(ARCHIVE_OUTPUT_NAME)をプロパティとして指定できるので,最初から出力先を指定しておけば良かったのです.

ビルドでハマる


Androidの場合,Ninjaを利用してビルドします.Ninjaはシングルコンフィギュレーション,つまりビルド設定を生成する際にDebugやReleaseを指定しておく必要があります.そのため,ビルドの際にはコンフィギュレーションを指定する必要はありません.

次のコマンドは,buildフォルダにビルド設定を生成した場合です.

cmake -G Ninja その他オプション -DCMAKE_BUILD_TYPE=Debug -B build
cmake --build build

一方,Xcodeはマルチコンフィギュレーション,つまり実際のビルド時にコンフィギュレーションを指定するタイプです.そのため,ビルドの手順がAndroidと若干異なります.

cmake -G Xcode その他のオプション -B build
cmake --build build --config Debug

2020年3月14日土曜日

コマンドラインでAndroid NDK向けにライブラリをビルドする

Android NDK向けのライブラリのビルド手順を探すと,基本的にはAndroid Studioでプロジェクトを作って,ビルドする,という情報が多い.

しかし!

Windowsのコマンドラインだけでビルドしたいのである.

というわけで,Android Stuidoがやってくれている作業を何とか再現してみる.

今回ターゲットにしたのは,libogg.Xiph.Org Foundationによって公開されているパテントフリーのマルチメディアコンテナフォーマットを扱うライブラリらしい.ぶっちゃけ,自分が使っているわけではないのでよく知らない.

取り合えず,このライブラリはCMake対応済みなので,最初のとっかかりとして楽だった.

まず,Javaの実行環境を用意する.OpneJDKをダウンロードしておいて,そのbinを含むフォルダへのパスをJAVA_HOMEとして設定しておく.

次に,Android SDK(Android Studioのダウンロードページの下の方にCommand line tools onlyとしてダウンロードリンクがある)をダウンロードし,展開すると,toolsフォルダがあるので,そのtoolsフォルダへのパスをANDROID_SDK_ROOTとする.

ANDROID_SDK_ROOT/binへのパスを環境変数PATHに足しておく.

sdkmanagerが実行できるようになるので,次のように必要なものをインストールする.

> sdkmanager "ndk;21.0.6113669"

すると,ANDROID_SDK_ROOT/ndk/21.0.6113669というフォルダが出来ているので,このフォルダをANDROID_NDK_HOMEとする.

次に,CMakeをインストールする.公式にAndroidに対応したのが3.7以降なので,3.7以降をインストールしておく.できれば最新版が望ましい.インストールの際は,全体で利用できるようにシステム環境変数のPATHにパスを登録しておくと,そのあとのあちこちで問題にならないかもしれない.

また,Ninja(https://ninja-build.org/)をダウンロードしておいて,適当にPATHに登録しておく.

次に,liboggのソースコードをダウンロードし,展開しておく.このフォルダへのパスをOGG_ROOTとする.

さて,ビルド用のフォルダはOGG_ROOTの外に作った方が良い.CMakeが生成する様々なファイルとliboggのファイルの区別がつきやすいからだ.

build/libogg-androidとでもしておこう.このフォルダに移動したら,ようやくCMakeを実行する.

> CMake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_TOOLCHAIN_FILE=ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=21 -DANDROID_ABI=arm64-v8a -DANDROID_LD=lld OGG_ROOT
> ninja

これで,libogg.aが出来ているので,あとはコレをAndroid NDKを利用しているアプリのプロジェクトに組み込めば良い.

-DANDROID云々の部分については,https://developer.android.com/ndk/guides/cmake を参照する.

LDをlldにしているのは好みの問題なのでご自由に.

最適化されたバージョンが欲しければ,-DCMAKE_BUILD_TYPE=Releaseとすれば良い.

2020年2月19日水曜日

ゲームプログラマのお仕事

ゲーム専用機やモバイル向けのゲームプログラマとして10年ほどやってきて,ゲームプログラマの仕事ってこういうのだったなぁ,という記録です.


  1. ゲームを作る
    当たり前の話ですが,ゲームプログラマの仕事の1つはゲームを作ることです.
    ただ,ゲームを作る,と言っても最近は色々な知識が必要なため,専門家に分かれていたりします.

    例えば,プレイヤーを作る人,ノンプレイヤーを作る人,UIの挙動を実装する人,カメラの動きを制御する人,AIを実装する人などなどです.

    プレイヤーやノンプレイヤーを作る人の場合,3Dモデルの読み込みや表示の制御,モーションの制御,モーションに合わせたサウンドの制御,移動による衝突の制御,など色々な知識が必要になったりもします.

    小規模なチームの場合,一人で色々なことをしなければならない場合もあります.

    最近は,ゲームエンジンが細かい部分はサポートしてくれますが,それでも,その機能はどういった機能で,どういったことが出来るのか,どう設定すれば良いのか,といった知識は必要なので,日々の学習は必須です.
  2. 仕様を決める
    仕様を決めるのは,プロデューサーだったり,ディレクターだったり,ゲームデザイナーだったり,プランナーだったり,そういった人たちの仕事だと思うかもしれませんが,最終的な仕様はソースコードに実装されたものなので,仕様を決めるのもプログラマの仕事になります.

    もちろん好き勝手に,こっちの方が面白そうだから,と変えたりするわけではありません.

    他の職種の人は,言った仕様がどれくらい実装が大変なのか,正確には分かりません.また,実現したいことと仕様が合致しているとも限りません.よくよく聞いてみると,別の方法で実装した方が楽だし,実現したいことも出来る,という場合もよくあります.

    プログラマからすると簡単な実装に思えることが,他の職種からは大変そうなことに思えるので,頼むのは申し訳ない,なんて思っている場合もあるのです.その逆もあります.

    ですので,お互いに足りていない情報を確認し合い,少なくともプレイ感覚を確認できる形まで実装するのに必要な仕様を固めるのもプログラマの仕事なのです.
  3. PCトラブルシューティング
    これは,ある程度規模の大きな会社だと,別途ヘルプデスクなどあるかもしれませんが,ちょっとしたPCのトラブル,例えば電源が付かないとか,そういった簡単なトラブルの解決も求められたりします.

    電池切れとか,電圧や電流が足りない,といった物理的な問題の場合もあるので,この辺は,ソフトウェアの問題ばかり調べていてドツボにはまることもあるかもしれません.
  4. ワークフローの構築
    どういうデータを作って,どういうフォーマットで,どこに提出するのか,というワークフローを構築するのもプログラマの仕事です.

    これは仕様を決めるのと似ていて,データを提出するアーティストやプランナーが作業しやすく,かつ,プログラマとしてもなるべく扱いやすいデータをどうするか決める必要があります.

    また,ミスしやすいデータがあるのであれば,手動でチェックする機能を用意したり,バージョン管理に載せる前に自動でチェックするための仕組みを用意するのもプログラマの仕事です.
  5. CI
    昨今流行りのCI環境の構築もプログラマの仕事です.なので,サーバーやファイヤーウォールなどに関する知識が必要になったりします.

    もちろん,大規模なプロジェクトや会社になれば専門家もいるでしょうが,小さい規模だと自分でやる必要があったりします.

    普段はデバッグ機能ありの状態でゲームを作っていて,いざ本番向けの状態のゲームをビルドしようとしたら,コンパイルエラーだらけ,という事態を避けるためにも,自動ビルドによるチェックなどは重要です.
  6. ライセンスチェック
    色々なミドルウェアを使ったり,組み込みたいという話になった場合の,最初の段階でのライセンスチェックもプログラマの仕事です.もちろん,最終的には法律の専門家にお任せするのが良いのですが,原則利用してはいけないライセンスのミドルウェアなどもあります.そういったものが要望に上がった場合,その時点で弾くのはプログラマの役目です.

    また,たまに拾ってきたソースコードを組み込んでしまうようなプログラマもいます.そういった人がいないか気にするためにも,多少はソフトウェアライセンスやオープンソースに関する知識も必要になります.
  7. エンジンの選定,改造,実装
    昨今,多くの企業がゲームエンジンを利用しているので,どのゲームエンジンを利用するのか,選定する作業が必要になります.エンジンによって得意なこと,不得意なことがあるので,ある程度色々なエンジンに関する知識が求められます.

    また,エンジンによっては改造可能な部分があったりするので,必要に応じて改造することも求められます.

    企業によっては,自社エンジンを持っている場合があり,そういった企業にいる場合は,エンジンの開発側に回ることもあります.
  8. 技術的なアドバイス
    例えば,モバイルであれば,今度出る端末はどんな特徴があって,作っているゲームのチェックのために購入する必要があるのか無いのか,といった相談をされることがあります.

    ゲーム専用機であれば,最近はマルチプラットフォームだったりするので,こういう仕様ってどのハードでも実現できるのか,といった相談を受けることがあります.
  9. スケジュールを立てる
    実装する内容が決まったら,どれくらいの期間で出来そうか,というスケジュールを立てる必要があります.これは,プログラマの経験や知識によって大きく変わるので,実際に担当者に予想を出してもらうのが重要です.
  10. スケジュールを調整する
    これは,全てのゲームプログラマがやるわけではないですが,他の職種の作業スケジュールに合わせて,実装する内容をいつまでに実装するのか,出来なさそうであれば,他の職種の作業タイミングをズラしてもらうのか,担当者を変えるのか,といったスケジュール調整も必要です.

    リードプログラマや,各専門分野のリードプログラマになると,こういったことも求められます.
  11. チーム内のコミュニケーションツールの整備
    最近は,Microsoft TeamsやSlackなどコラボレーションツールが充実してきていますが,利用できない場合には,自分たちでSlackクローンを用意したり,その他のコミュニケーションツールを導入する必要があったりします.
  12. ドキュメントの整備
    ゲームプログラマの仕事は,ゲームを作るだけではありません.開発環境を構築するためのドキュメント,ワークフローに関するドキュメント,セーブや課金に関する資料整備,開発中の便利機能やQAを楽にするための機能に関するドキュメントなど,思っている以上に文章を書くことがあります.

    このドキュメントを読むのはプログラマだけでなく,他の職種向けだったりする場合もあるので,これくらいは分かるだろう,という前提が間違っていることも多々あります.

    例えば,コマンドラインを実行してください,と書いても,プログラマ以外はそもそもコマンドラインって何なのか,ということだってあり得ます.

    プログラマ以外にも通じる文章の書き方を学ぶ必要があるわけです.
  13. バグの原因調査
    最終的に,プログラマ以外の作業が原因と判明することも多々ありますが,だいたいの原因不明のバグの調査は,まずプログラマがやることになります.

    例えば,キャラクターがおかしな動きをする,という話になったとき,そもそもモーションのデータがおかしいのか,モーションの指定がおかしいのか,はたまた特定の条件の場合のみモーションの計算がおかしいのか,と色々と原因が考えられます.

    データがおかしい,ということになった場合でも,じゃあどう直すのが良いのか,ということが分からない場合もあります.

    そのためにも,ゲームプログラマは,データの直し方,もある程度知っている必要があるのです.MayaやBlenderといったDCCツールの使い方は分からなくても,この関節の回転のデータがおかしいので,そのデータを直してみてください,というくらいなら出来るはずです.
  14. ツールの開発
    開発中に問題のあるデータが見つかった場合,それを一括で修正するツールを実装する場合があります.

    CIのために,自動でデータをチェックするツールを実装する場合もあります.

    他にも,開発中にはいろいろな理由で色々なツールを作ることがあります.

    プログラマしか使わないツールであれば,コマンドラインで作ってしまうのも手ですが,他の職種も扱うツールの場合,GUIがあった方が良いこともあります.その場合,さっとC#などでツールを作れる知識も必要になります.

    他にも,例えばddsの画像をpngに変換する必要がある,というようなデータフォーマットの変換ツールを作ることもあります.この辺はややこしいので、既存のツールを内包する形にすることが多いと思いますが,その場合,どういった既存のツールがあって,利用できそうか,という知識が必要になります.

    Excelなどを改造してツールにすることもあるので,VBAなんかの知識もあると役立ったりします.
  15. 流行りのゲームやアニメに関する情報源
    ふわっと,何かこういうイメージのゲームってあるか,という質問だったり,こういうアニメの表現って出来るか,であったり,何か他のものを参照するための情報を求められることもあります.

    この辺は,ゲームプログラマに限らないのですが,実装が絡んできそうな内容の場合,やはりプログラマに質問が来たりするので,実際に詳しく知っているわけではなくても良いのですが,特徴的なゲームだったり,アニメだったりは名前くらいは押さえておいたほうが良かったりします.
  16. 処理時間の改善
    FPS(1秒当たりの画面の更新回数)が低いと,カクカクとした動きに見えたり,反応が悪いように感じたりするので,時間がかかっている処理を改善するのもプログラマの仕事です.

    処理時間を短くするには,原因を調査するためのプロファイラの使い方の知識であったり,原因が分かった際の対処方法に関する知識が必要だったりします.

    例えば,特定のAPIの呼び出しがブロックしていて時間がかかっている場合,非同期に呼び出せるAPIが無いか,呼び出せるなら,その部分を非同期にできないか,といったことを考えたりします.

    他にも,そもそもアルゴリズムが悪い場合もあるので,ある程度,その分野の基本的なアルゴリズムは知っておいた方が良いでしょう.例えば,単純な幅優先探索に置き換えるだけで劇的な改善をしたこともあります.

    また,処理時間を短くするのは,何もゲームの中だけの話ではありません.ツールの起動にやたらと時間がかかったり,キャラクターの設定に関するデータの出力にやたらと時間がかかったり,といった場合を改善するのもプログラマの仕事です.

    それまで1分ほどかかっていた作業が数秒程度になった,なんてこともあります.
思い付く範囲でダラダラと書いてみたところ,結構な量になってしまった.

書いてみて,結構幅広い知識を求められるよなぁ,と.

もちろん,最初から全部知っていろというわけではないのですが,スペシャリストになるのが難しそうであれば,色々と知っていた方が選択肢は多くなるのかなぁ,という気がします.

2020年2月3日月曜日

Substance Designer入門 Lesson3-01のパラメータ

Substance Designer入門

この本を読んでいて,そのままだとサンプルと同じ感じにする方法が分からなかったので,サンプルを見ながら,この数値にすればOK,というのを抜き出してみました.

Lesson 3-01

葉っぱの筋を作る,に出てくるTransformation 2D

Specific ParametersのTransform Matrixで,Edit Matrixを選び,X1を1.6153,Y1を0,X2を0,Y2を0.7413に設定する.
Offsetは図の通りに.

Levelsは,Specific Parametersの一番右のアイコンを押して,数値を指定できる状態にして,Level Out Lowを1に(下側の黒に相当).Level Out Highを0.6717903に(下側の白に相当).

草を並べる,のところからいくつか数値が図と違うようです.Tile SamplerのX Amountは19です.

Sizeも,最終的にはXが3.85で,Yが0.8になっています.

また,ColorのColor Randomに0.3が入っています.

Maskに使うShapeは,Scaleが0.86,SizeのXが0.76,Yが1になっています.

Gradient Mapは同じようにするのが大変です.


  • Position 0
    • R: 150,G: 190,B: 105,A: 255
  • Position 0.041
    • R: 22,G: 28,B: 15,A: 255
  • Position 0.204
    • R:19,G: 27,B: 3,A: 255
  • Position 0.317
    • R: 26,G: 40,B: 13,A: 255
  • Position 0.470
    • R: 76,G: 90,B: 33,A: 255
  • Position 0.641
    • R: 148,G 165,B: 92,A: 255
  • Position 0.684
    • R: 139,G: 153,B: 90,A: 255
  • Position 0.737
    • R: 159,G: 173,B: 107,A: 255
  • Position 0.782
    • R: 152,G:165,B:109,A: 255
  • Position 0.822
    • R: 217,G: 232,B: 160,A: 255
  • Position 0.865
    • R: 162,G: 173,B: 114,A: 255
  • Position 0.943
    • R: 162,G: 173,B: 114,A: 255
草を切り抜く,の部分のLevelsはLevel in Mid(上の灰色)を0.05353075に設定します.

プログラマのサガなのか,サンプルとの差があると何が原因なのか,ついつい調べてしまいますが,Substance Designerはちゃんと数値にアクセスする手段も用意されているようです.

Substance Designer入門にはちゃんとサンプルデータが付いてきていて,そちらはコメント付きで分かりやすくなっているので,プログラマの場合,そのサンプルを見て,デフォルトから変更されている部分を抽出すれば,サンプルと同じものが出来て,安心できると思います.