水ノ茉の宣伝
準備中...
ゲームを作る予定なの水ノ茉
始まり
描画エンジニアになりたい方の入門編にもちょうどよいコンテンツ。
そう、アウトライン(輪郭線)
(尚主観。異論は認めよう。)
それを幾つかの実装方法で描いていきます。
アウトライン(輪郭線)とは
読んで字の如く。
描画まわりの専門用語が一切必要の無い優しい子です。
これ以上の説明はない。
こういう感じ


これはエンジン改造でバカバカに手を加えているので、これと同等の見た目は作れないです。
(まぁまぁ大変なのよ。我ながら自信作だけど。ポストだけなのに線綺麗でしょー。えっへん。)
さあ、教えてください。誰に興味があるんですの?
???「う、うーむ……」
???「ポストプロセスマテリアル、かなあ」
(これをやりたくて記事を書いた。)
ポストプロセスマテリアルとは
ポストエフェクト。
ポストプロセスマテリアルを作る



カスタムノードで組んでいく
一番簡単な4回サンプリングする方法程度であれば、ノードでも組めますが、エンジニアならコードで書いた方が理解が早いと思うので、カスタムノードで書いていきます。
どの程度の粒度が分かりやすいかは、ひとによると思うので、私が飽きるまでは極力細かく書いていきます。
まずはこんな感じにノードを組んでいく

SceneTexture




TextureCoordinate


ScalarParameter






Custom





カスタムノードを書く
実際にノードを書いてみましょうか。
皆さんはコピペするだけですけど。
写し書きしながらの方が覚えやすい方はチマチマ書いてくださいね。
このあたりは自分の作業スタイルに従うのです。
各関数説明も入れていきます。
コピペ


コード全文
const uint MaxOffset = 4;
const float2 Offsets[MaxOffset] = {
float2( 0.0, -1.0),
float2( 1.0, 0.0),
float2( 0.0, 1.0),
float2(-1.0, 0.0),
};
float Weight = 0.0;
UNROLL
for (uint i = 0; i < MaxOffset; ++i)
{
float2 NewUV = UV + Radius * Offsets[i] * InvSize;
float2 NewClampedUV = ClampSceneTextureUV(ViewportUVToSceneTextureUV(NewUV, PPI_SceneDepth), PPI_SceneDepth);
float NewSceneDepth = SceneTextureLookup(NewClampedUV, PPI_SceneDepth, 0).r;
Weight += SceneDepth - NewSceneDepth;
}
return saturate(PositiveClampedPow(Weight, Bias) * Intensity);
ViewportUVToSceneTextureUV
ビューポート座標からバッファ座標に変換しています。
入門編で触れるには難しい内容ですが、Unreal Engineは動的解像度対応しているため、画面のサイズとバッファのサイズが必ずしも一致している訳ではありません。その辺りと互換性を取るために必要なフローです。
少し慣れている方からしたら、動的解像度はそもそもPS5とかの一部プラットフォームだけじゃない?と疑問に思うことでしょう。UEも基本的にはそれに従うので疑問は合っています。
ただ、エディタウィンドウで画面サイズが頻繁に変わる際、例えば1920×1080から1280×720にリサイズしたとしましょう。
リサイズしても内部で確保されるバッファサイズは1920×1080のままになります。起動してから一番大きいバッファサイズを維持し続ける挙動なのです。その都度メモリ確保するよりクリアした方が安定するというアレです。
これが実質的に動的解像度挙動と近いので、結局はこの変換入れておいた方が無難という訳なのです。他にもスクリーンパーセンテージとかもありますし。
ClampSceneTextureUV
バッファ座標が範囲外を示さないようにクランプする関数です。
ポイントサンプラの場合は普通のクランプ、バイリニアサンプラの場合は1ピクセル余裕を持ったクランプをしてくれています。
SceneTextureLookup
GBufferを取得する関数です。
先ほどSceneTextureノードを配置したと思います。
その中で呼ばれてるのがこの子です。
この子は例外なくfloat4で返却するので、用途に合ったチャンネルだけ使用します。
SceneDepthの場合はRチャンネルだけ格納されていて、その他は0埋めだった気がします。
UNROLL
過去に書いたと思ったけど、途中で飽きちゃったのね、わたし。
固定長なループの場合はUNROLLを指定することで簡単に最適化ができます。
その程度の理解で十分だと思います。
PositiveClampedPow
皆さんがノードで使っているpowは、実は普通のpowじゃありません。
内部で0.0以下の値はpowせずに、0.0を返すような三項演算子が組み込まれているのです。
この辺りは商用ゲームエンジンの優しい配慮って感じがして、良きですね。
輪郭線とご対面
怠い関数説明も終わりました。
ピンを繋げて見た目を確認しましょうか。







荒ぶる輪郭線の怒りを収める
めっちゃジラジラしますよね。
輪郭線がご乱心です。
これは、ポストプロセスマテリアルの初期設定とアンチエイリアスのデフォルトであるTSRの相性がゴミだから発生しています。
ジッタリングを考慮すれば済む話ですが、今回はそういうまどろっこしいことはなしで、描画パスの位置を変える方向で抑制します。
そもそもトーンマップの後に輪郭線を描きたいというケースがほぼないでしょう。被写界深度ガン無視しちゃうし。
以下に従ってポストプロセスマテリアルの設定を変更します。

変更後は遠景は相変わらずジラジラしていますが、それ以外は抑制されたでしょう。
Blendable Locationについてはこの記事で触れてます。1つ上のバージョンの5.4ですが。
遠景マスク
お空に輪郭線を描きたいですか?
少なくとも私は「いいえ」です。
マスクしちゃいましょうか。
const uint MaxOffset = 4;
const float2 Offsets[MaxOffset] = {
float2( 0.0, -1.0),
float2( 1.0, 0.0),
float2( 0.0, 1.0),
float2(-1.0, 0.0),
};
float Weight = 0.0;
UNROLL
for (uint i = 0; i < MaxOffset; ++i)
{
float2 NewUV = UV + Radius * Offsets[i] * InvSize;
float2 NewClampedUV = ClampSceneTextureUV(ViewportUVToSceneTextureUV(NewUV, PPI_SceneDepth), PPI_SceneDepth);
float NewSceneDepth = SceneTextureLookup(NewClampedUV, PPI_SceneDepth, 0).r;
Weight += SceneDepth - NewSceneDepth;
}
float SkyMask = step(SceneDepth, 1000000.0);
return saturate(PositiveClampedPow(Weight, Bias) * Intensity) * SkyMask;

もう少しいい感じの遠景マスク
遠景マスクをしたら輪郭部分が消えちゃいましたね。
こういう時はサンプリング内の一番手前の深度を使うことで解消できます。
const uint MaxOffset = 4;
const float2 Offsets[MaxOffset] = {
float2( 0.0, -1.0),
float2( 1.0, 0.0),
float2( 0.0, 1.0),
float2(-1.0, 0.0),
};
float Weight = 0.0;
float NearSceneDepth = SceneDepth;
UNROLL
for (uint i = 0; i < MaxOffset; ++i)
{
float2 NewUV = UV + Radius * Offsets[i] * InvSize;
float2 NewClampedUV = ClampSceneTextureUV(ViewportUVToSceneTextureUV(NewUV, PPI_SceneDepth), PPI_SceneDepth);
float NewSceneDepth = SceneTextureLookup(NewClampedUV, PPI_SceneDepth, 0).r;
Weight += SceneDepth - NewSceneDepth;
NearSceneDepth = min(NewSceneDepth, NearSceneDepth);
}
float SkyMask = step(NearSceneDepth, 1000000.0);
return saturate(PositiveClampedPow(Weight, Bias) * Intensity) * SkyMask;

飽きた


おわり!!!
一番シンプルな輪郭線でした。
そのうち、プラグイン拡張とエンジン改造のお二方のルートを解放する予定です。
アウトライン関連
雑談
メモに溜まった雑談を解放したいから急いでおまけの技術パートを書いたよね。
3時間の突貫クオリティ。ん~。酷い。
まぁでも、コードは使えるから、必要最低限は満たしているでしょう。
それにしてもエンジン改造で作った方、毛先が綺麗。
背面法で法線調整するのが嫌過ぎるという理由から、割と頑張ったら背面法より綺麗になった気がする。

ちなみにこういう細い線より、上の昔のアニメみたいな太めの線の方が好み。
のののの。

ルート選択画面を作ることでモチベーションを最大限までブーストして走り切ってやりました。
どうですか。すごいでしょう。疲れた。
勢いとは裏腹にのんびりとした Turn Off the Lights を聴きながらここまで頑張りました。
「龍」は「竜」の旧字体らしい
風紀委員長の龍司くん。
僕の読み上げツールでは、何故か難しい方の「蘢」や「籠」として分類されました。
おおかた予想は付きます。
オフセットし過ぎて冠を切り取ったのでしょうと。
ただ腑に落ちない点もあります。
オフセット幅は前回の改修よりも以前から、空き領域を超過することが無いようにクランプ処理を入れています。
これぐらいしか予想が付かないけど、処理的にありえないという矛盾です。
さて、現実はどうでしょうか。
データセットを調べてみましょう。
龍のUnicodeは40845です。
※文字画像はUnicodeを末尾に付けて管理しています。
――あれ?
見つからない。
え?
除外文字に入れた覚えないけど、一応ラベル情報を見てみるか。
うぇ?!
「龍」って「竜」の旧字体なの?!
旧字体のイメージが現代では使わない古い漢字という先入観があったので、かなり驚きました。
現実世界でも人名として健在ですし。
へぇー。
またひとつ賢くなってしまいました。
「龍」を除外文字から外して、学習対象に入れたら無事解消しました。
Shadowは深度差、Shadeは内積解なイメージなのよさ
顔陰、Face Shadowが一般的な呼称ですが、内積でしか求めてないんだからFace Shadeやろと、個人環境ではShadeという名称にしています。
言葉の揺れを厳密に気にするほど意識高いエンジニアじゃないのですが、ある領域においては、意外と気にしちゃいます。
オトメき 発売日延期

悲しい。
でも全年齢のゲームは年単位の延期とかよくあることだし、それに比べたら優しいですね。
回収額が比にならないと思うので、単純な比較はできないと思いますけど。
うーむ。
延期かぁ。
夏休みを取る口実が消失してしまった。
まぁコード書くの楽しいから今年はいいかな。
と言いつつ、1日だけセレオブの荷物受け取りで消化しました。
セレオブを無事に届けてくれるであろう、運送会社の方々に感謝。
セレオブが届いたぞ


いえーい。
駿河屋以外は発売日に到着しました。
あそこは遅いのがデフォルトなので仕方がないですね。
―――これねぇ。
毎回思いはするんだけど、特典目当てで複数購入ってアホなんだよねぇ。
でもねぇ、アホでいいんだよねぇ。
ということで円盤の在庫が3つあります。
4店舗で買ったけど若干の後悔がある。
メインキャラクターは好みに関係なく制覇しておくべきだった。
セレオブのリアイベ
リアイベあるらしいですね。
私は行かんけど。
ゆずショップといいコラボカフェといい、独りで行くことがない私です。
基本的に悪友と近況報告のご飯会の時にしか行かない。
出歩くの怠いんだよなぁ。
たぶん、共通ルートかな
セレオブのネタバレを含みます。
過去のわたくし「あ」というタイトルだけ付けていましたわ。
ふざるんじゃねぇですの。
これじゃ分かりませんわよ。
たぶん、共通ルートの話なんですかねぇ。
パスタ茹でるときに塩ぶん投げる理由に沸点と吹きこぼれが出てくるあたり賢くて可愛らしいなと思う反面、メシマズ要素感あって怖かった。普通に塩味やろ・・・
はえー。硫化アリル、勉強になる。
数字による結果は人を容易に黙らせる
圧倒的同意ですが、その結果を評価する対象が人間であるという点が唯一の欠点と思いますね。
温泉女子会
セレオブのネタバレを含みます。
さてと、片手間に進めていましたが、ちょっくらゲームとだけ向き合いますかね。
たぶんそろそろ共通ルートを抜け出して個にフォーカスが行く気がする。
温泉女子会、確かに皆さんデカいっすね。
おっぱいが。
この会話を虚無の三司さんに聞かせたらブチギレそう。
無い胸を寄せてるあのシーンめっちゃ面白かった。
つか別にくくるさんも小さくねぇだろ。
これで小さいって基準バグり過ぎやろ。
巨乳撲滅委員会は草。
あやせさん加入必須ですね!
ちとせさんも悪ノリで入りそう?
ちなみにちとせさん、茉優先輩の次ぐらいに好きです。
割とサブキャラにカテゴライズされる方々に惹かれる性格なのかもしれません。
あのー。
御子息御令嬢とかいう社会的地位ないし能力が高い人間が集まっている割には、ファンクラブの名称、頭悪すぎないか?
いい意味でね。
う~ん。
エロ本に向けられる殺意が高過ぎて涙が出ます。
でも私はこの気持ちがわからん。
現代っ子だから紙媒体じゃなくて、電子媒体なのよ。
隠し場所もなにもねぇのだわ。
満場一致で焼却処分は辛いでしょ。
ハイライトの輪郭線を消失させるこの魅せ方、結構好きかも。
今度シェーダー書く時の参考にしよう。
あとはEyeシェーダー頑張りたい気持ちもあるけど、D.C.Ⅲの世界って、パーツが限られている作りだから、そこまで作りこみ必要ない感じもするのよね。
ガチガチのセルルックだし、目標としているのはアニメ寄り。
なんか、あれですね。
結局のところ今はコード書くことが好きなので、ゲーム画面と向き合っても、それを再現したい欲を抑えられないですね。
よく言えば技術誇示に貪欲、悪く言えばゲームにそこまで興味がないのかなぁ・・・
プログラムは溜めた知見を使いまわせるないし、それを土台に次にステージに進めるのが楽しいですよね。
さてと、話をゲームに戻しますか。
筆者のゲーム経験値が少ないだけなのか、記憶の欠如が甚だしいだけかもしれませんが、共通ルートでここまで露骨に好意というかルートを示してくれる作品ってなんか、あったっけかな?
いや、あったはず、思い出せねぇけど。
奏命さんの髪色と夜空、映えますね。
とても綺麗です。
このキャラをぼかして乗せる手法。
ゲームでは処理負荷的にあまり見かけないですが、CG絵とかではよくある手法で、綺麗ですよね。
はぁー。
ゲームすると結局作りたいモノが増えてなんかモヤモヤする。
もっともっと力が欲しいですね。
圧倒的な力でやりたいことを全部、片っ端から楽しみたい。
奏命
セレオブのネタバレを含みます。
奏命さんは読書が好きなんですね。
哲学ですかぁ。
北条姉妹の部屋着、ええやん!!
あ、マイナスポイント発見。
奏命さんの心の声は奏命で表記して()で囲ってくれないと伝わりづらい。
1か所はシュミレーションと誤字してますね。
重箱隅攻撃。
シミュレーションが正しいですわ。
もうすこし介入イベントがあると思ったけど、考えてみれば圧倒的な権力の庇護下である以上、そんなことはないのか。
合理的ではあるものの、はらはらどきどきの王道イベントがないのはもったいない。
共通ルートからストレートに会長√突入して約47万文字。
ふぁぁ。
流石に眠い。
夜中というか朝の5時です。
社会人になってから初めて連続で8時間以上ゲームしたわ。
物語って素敵ですね。
ふぁぁぁ。
気分いいから寝よ。
残りの休日2日で3人攻略しなければ。
蓼科
セレオブのネタバレを含みます。
蓼科さんは素直。
汐莉ぐらい感情バカ出しな子は良いですね。
クレイジーサイコレズかと思ったけど、そうじゃないのね。
てっきりこういう血の繋がりの設定は、ヒロイン側に設けるかと思いましたが、サブキャラの方でしたか。
王道設定はいいと思います。
遺伝子を分割せずに纏めていたら、奏命さん以上の化け物が出来上がっていた可能性もあるんですかね。
まぁでも単体で奏命さんに追い付いたとて、北条姉妹というブーストが存在する以上、この世界線で崩すことは無理ですかね。
うーん。奏命さんルートでも思いましたが、ヒロイン視点の台詞表記、結構悪いですね。
切り替えタイミングを逃すと、どちらの視点か分からない。
というか分かりにくいから雰囲気が崩れる。
流石に改善ポイントですね。もったいない。
くくる
セレオブのネタバレを含みます。
ファイブについては、タナトスさんこと一姫さんのお陰で、概ね予想通りでしたね。
あの世界と同程度の非人道的なことをしていましたね。
人間の業の深さだけで言えば創作世界の方が想像の範疇でしかないので優しい部類と思いますが。
七「実に幸せそうだね」
圧倒的同意です。
微笑ましい光景です。
人工物だけで構成されている絵とは、とても思えないほどに。
先輩も良かったことでしょう。
家族が作れたくくるさんの次の目標はなんでしょうかね。
気になります。
若干の心残りとしては、くくるさんを選ばない世界線で、七先輩が安心して卒業できるのかという点ですね。
うーん。
あーでも、トウリさんが居るのか。
ふむ。なるほど。トウリさんが上手いこと話を纏めてくれるでしょう。自己完結したわ。
トウリ
セレオブのネタバレを含みます。
最初、奏命さんルートから進めようと遊んでいた際、無難に宥めようとしたら展開的に個人ルート突入しそうな勢いがしたので、急いで履歴から戻りましたね。
不意打ちでした。
一色家ってさ、チートカード過ぎない?
七海さんといい、新海妹といい、桜良さんといい、妹枠の子は、抑制された感情の爆発具合がいいですよねぇ。
――新海妹って義妹だっけ?
んんん・・・
記憶の欠落が・・・
また遊んで上書きせねば。
あの子に関しては紙袋が印象的過ぎて、他の事柄が飛んだわ。
もー、天才でしょ。あの子。
今思い返しても面白れぇ女。
新海兄には、将来的に音声再生でもお世話になる予定なので、どのみちサンプル集めのためにももう1回プレイしないといけないんですよね。
ちなみにエロゲ初心者には9-nine-おすすめです。
王道を歩みつつも、作品を遊び続けることで納得するストーリー展開。
あの感覚を年々味わえた当時は最高でしたが、それを抜きにしても十分に得られるモノがあります。
エッチシーンは、ぱれっと特有の違和感は拭えないですが、慣れると気にならなくなります。
昔から変わってないよねぇ。
シリーズに沿って遊んだ方がいいです。絶対に。
ちなみにパフェクイーンはまだ未攻略です。
そのタイミングぐらいで社会人になったので、ゲームを辞めてコード書くだけの日々になりました。
そして今はゲームとコードを半々にする努力期間中です。
くくるさん同様に想像の範疇でしたが、想像した王道を進んでくれて大変満足。
僕はこういう物語を見たかったのです。
トウリさんルート最高です!!!
流石、私が一目惚れした子の歩んだ道です!!!
んんんんんん。
むふふふふふ。
大満足。
一番好き。
総括
セレオブのネタバレを含みます。
各ルート20万文字前後のボリュームですね。
エッチなシーンの擬音も含めているので、それを除いたら、もう少し減るでしょうが。
内製エンジンだから実装が難しかったのでしょうが、フローチャートは実装して欲しかったですね。
誰のどのシーンなのかが、俯瞰、時系列で把握できる機能が欲しかった。
超解像度に関しては、CG絵をズームすることが多々あったから、その際の品質改善の一環として導入したのかな。
実験的機能っていう表記、これプログラマ以外は馴染みがないから避けるべきとは思いましたね。
同業であれば実験的機能を使ったらなにかしらの不都合が生じる可能性があるのだろうと、すぐに結びつきますが、一般のユーザーがそこまで想定されるかは、期待できない。
てか、この程度の超解像度なら全チェックできるだろうから、実験的の表記要らないと思うんですよね。
個人ルートの進入が素直に進むゲーム構成は助かりました。悪く言えば、物足りないのですが、これ、時と場合によるんですよね。
時間がない時にこういう仕様と出くわすとウザい、じっくり遊びたい時には、遊び要素がなさ過ぎてつまらない。
この辺りのバランス調整は面倒そうですね。
そして物語を通してもやっぱり、トウリさん、くくるさん、好きですね。
北条姉妹と会長を交えてエッチして欲しかった反面、常識的な従者で会長のあの性格を考えると合理性が無さ過ぎて無理かと自己完結。
姉妹を下から見た時が絶景でした。
太ももってエッチだよな。
北条姉妹の私服可愛過ぎる。
主人公には悪いが、和服を着た姉妹にもう一度踏まれて欲しかった。
眺めが最高過ぎるだろ。
ゆずソフトみたいにルート用意してくれたら嬉しいのに。
一応話の合理性は持たせられると思うんですよ。
北条家に婿入りすれば間接的に手に入る訳ですし。
一色家という設定、強過ぎてなんでもあり過ぎる。
3連休か…
忘れてたけど3連休じゃん。
シークレットラブ(仮)遊べばよかった。
時すでに遅し。他にやることあるから諦めよ。
てかこの作品、略称なんだろう?シーラブ?シクラブ?
セレオブを遊んだのを最後に、コード書きすぎてる気がする。
遊ぶ宣言どこ行った・・・
購入したエロゲをデスクトップに配置する遊びをしていたらCドライブ枯渇してしまいました。


次買い替えるときは2TBのM.2 SSDで爆速エロゲ立ち上げを目指したいと思います。



