2023.10.9
ロリノキョウイゾンことラグナクリムゾンというアニメが性癖にブッ刺さりです。今のところ二話までやっているのですが、厨二アニメの皮を被った最強の性癖コンテンツであることを皆さんにレクチャーしようと思います。
まず一話の冒頭のロリとの共依存関係は語るまでもなく最高だよね。街で一番の力を持ったロリと昨今のハイテク家事ロボットに家事能力で圧勝しながらも戦闘能力でギリギリ負けそうなヒョロ主人公という構図が我が家でのニトリの激安ロボット掃除機と僕みたいな力関係の逆転をありありと描いているよね。その後主人公が覚醒するわけだけどそしたらロリとかショージキ足手纏いな訳でここからの戦いにはついていけないチャオズより1兆倍好感度の高いロリであろうと置いていかざるを得ない共依存の崩壊とそれを為す主人公、いや僕の心に襲いかかる自罰感情と喪失感は儚くもほろ苦い初恋の失恋模様を6時間コトコトと煮詰めたような最高のフレーバーを醸し出している。僕が現実でもその苦味を味わおうとハンディ買ってから最近使わなくなったニトリロボット掃除機にペコペコ土下座していると「メイド 男の娘 性別は自由に変更可能 弱気 内心は腹黒」でbingAIで検索したら「え、えっちな話題禁止!べつの話題にしてっ///!」と青いアイコンを真っ赤に赤面させて怒られそうな性癖刺殺人間が出てきて今後の展開から強烈に匂ってくるえっちアニメが「ずんだホライズン」じゃなくて「ロリノキョウイゾン」なワケ。
端的に描写するとこのようなアニメです。この日記では然る要注意アニメの動向を逐一フォローし報告しようと思います。よろしくお願いします。
2023.9.25
歌舞伎町に子猫サイズのネズミが出たらしいです。物価高の昨今において粗食で体重をどんどん減らしている僕がいる一方でなんたる生意気でしょうか。しかもタダです。歌舞伎町に転がっているタダの食事にありついてぶくぶくと育っていったとのことです。
しかしネズミが大きくなっているというのは好都合です。僕のような160cm台のチビが紛れていてもバレないと思います。つまりタダ飯にありつけるということです。170cm以上あれば流石に気づかれるでしょう。つまり170cm以上にはネズミ権がありません。これは170cm未満に与えられたタダ飯食らいの権利なわけです。
しかしこの現代の錬金術にも欠点があります。それは野生の厳しい生態系に取り込まれるということです。つまりネズミの捕食者である猫が集まってきます。ごろにゃーごろごろ、と小さい猫からデブ猫まで僕の周りに集まってきて僕のあちこちにはむっとかぶりつくわけです。こんなことをされたら僕は視神経から流れ込むネコにゃん可愛すぎウイルスによって命を落とします。
世の中にはこのウイルスに抗体のあるイヌハと呼ばれる稀有な人種がいると聞きます。イヌハの皆様は是非この方法を試してみてください。
2023.9.21
最近はほとんど食事は自炊しているのでその成果を確かめようとクレカの請求を見たらdlsiteとかいう謎の機関にお金が流れていました。
その根源を断とうとdlsiteに訪れると以前買った同人誌の続編が出ていました。つまり客観的な評価によればこれに似た傾向を持つ同人誌が僕の資金的余裕を減らしているのだということになります。タイトルには「催眠」と書かれています。一体何を指し示しているのでしょうか。同様の出費が確認されるfanzaというサイトでもこのキーワードを調べたのですがこちらでは一件もヒットしません。謎は深まるばかりです……。
しかし何でしょうか、この胸の高鳴りは。この「催眠」というキーワードにとてつもない親近感を覚えます。さらに目を背けようと一文字伏せて「催◯」としても一層心拍数が高鳴るばかりです。もしかしてこの「催眠」というのは僕にとって、とても大切なものだったのではないでしょうか。
試しに既に買っていた「催眠」という名を冠する同人誌を読んでみます。ぬぬっ!この現代社会の枠組みを打ち壊す全能感!非モテすら包み込む肯定感!購入する手が止まらない!この同人誌も!こっちの同人誌m!
「催眠にかかった振りしてたの♡あなたのことが大好き♡!」
うわあああああああああああああ!!!!催眠のフリをした純愛だあああああああああぁぁぁぁぁぁぁ、、、、、、……………………………
………………………………
…………
……ショックで何か大切なことを忘れてしまったような気がします。dlsiteが開いてあったので適当に見ていると「催眠」と「NTR」という文字が目に入る度に脳が欠けてしまったかのような感覚を覚えます。ですが「催眠NTR」という言葉を見ると高揚感が湧いてくるのです。つまり文脈が大事であって、純愛はいいけど催眠から純愛の流れにしてはいけないということが今日、僕がこの日記を通して伝えたかったことです。
2023.9.12
今朝も来るべき始業時間をベッドでニャオハを抱きながら待っていたのですがインターフォンが鳴り響きます。そういえば池袋中の書店に一つも存在しなかったよつばと1,2巻を注文していて、それかなと思って扉を開けると現れたのは八百屋。人間の基本的な栄養の一つであるよつばとがついに野菜認定されたのかと思いましたが「今朝いい梨が入ったので行商しにきましたー」とどうやらよつばとは取り扱っていないようでした。
しかしなんか爽やかな笑顔で今朝入った梨の素晴らしさを語る八百屋さんを見て「うんうん、これもよつばとだな」と思いつつ聞いているとアレクサが「ご主人様。朝会のお時間です。」と平坦な電子音声(セリフ的に平坦な電子音声はクーデレメイドを思わせて適している)で告げてきます。
なるほど、つまりこれは野外で育てているオクラに釣られてインターフォンを鳴らした八百屋に対して出てきたよぼよぼパジャマの男はどうやら部屋の中で①スマートスピーカーをメイド扱いしてリマインダー設定のことを調教と形容している②メイドをスマートスピーカー扱いして調教のことをリマインダー設定と形容している③ちなみにリマインダーの口調はメイドだけでなく内容ごとに妹、幼馴染、後輩と多種多様な口調を取り揃えている、というような印象を与えてしまったということです。
それに気づいた瞬間に僕が七色に光りながら爆発したので梨の話はナシになりました!
2023.9.10
ちょっと行ったところのトキワ荘ミュージアムでよつばとの特別展示があるらしいので、池袋中を探し回ってよつばとを全巻買ってきました。(よつばとは電子書籍がない)
しかしあのほのぼのマンガで癒されるために池袋の喧騒の中を歩き回るというのも皮肉なものだな、と空を見上げると日がすっかり暮れています。日曜日が終わったのです。
5歳の頃は毎日が休みみたいなもので、何にもない日でも鮮烈な印象を与える何かが必ずあって、あと美少女の幼馴染がいて天才子役の名を恣にして萌え萌え妹の萌え萌え萌えな萌え萌え萌え萌え
気づくと時計の針が午前3時を回っていました。過去を改変した長めの妄想に入っていたことに気づき、大人になってしまったのだな、と天井にため息を投げかけます。誰にだってあった、世界が今よりずっと明るく見えていた頃の話。そう、僕も5歳の頃は木々や虫に魂を感じたり、ボーイッシュな幼馴染のふと見せる女の子じみた素振りに萌えを感じたり、その子と一緒に帰った帰り道でクラスメイトの男子に揶揄われて少し気まずくなったり、萌え萌えな妹に萌えで萌えなあんなことやこんなことを
気づくと始業時間に設定したアラームがなっています。僕もまともな社会人になったのだな、と自嘲し、パソコンの電源をつけます。仕事が終わったら過分に粉飾した僕の最強妄想過去デッキを持ってノスタルジーに打ち勝つ気持ちでよつばとを読もうと思います。
2023.9.7
先日、フライパンをつかむやつが溶けました。しばらくは誤魔化しつつ使っていたのですが、あまりの安定感のなさに鉄骨綱渡りの形相でフライパンをコンロから食卓に持って行くことに疲れ、ようやく昨日届いたのがこちらの『マルチハンドル』です。
手に馴染むフィットグリップ設計によりデザインされており、よく手に馴染みます。どれくらい手に馴染むかというとこれを握りしめながらシチュボを聴くと女の子と手を繋いで添い寝しているかのような感覚を覚えることができるかもしれません。つまり非モテでもこれを使ってフライパンを振うことで彼女との料理を妄想することができるわけですが、目を開ければその彼女は具材を詰められた上で火に炙られている。そんなことは起こりえない程度には普通に握りやすいです。
とりあえず鍋にセットしようとすると、明らかに挟む部分の広さが足りません。トグルレバーを動かしても挟む角度を変えても挟めません。ここでちょっとした工夫をしてあげると……
チョキ
挟む隙間が広がりました! 配送1日目とはとても思えないアンティーク感やダメージ感も演出する革命的な一手にアンビリーバブル!私、感激!
ちなみにトグルレバーについているボタンを押しても隙間を広げることができるそうですよ。
これはパッドです。どんなフライパンにも大股を開ける品の無さ。正直引きます。引き取ります。ゴムを切らずにこんな感じで使われているのを引き取るので誰か僕のと交換してください。至急ご連絡ください。僕のやつ買ったばっかなんです。
2023.9.2(dxcompiler.libでシェーダーコンパイルしてPIXでシェーダーデバッグ)
DXCompilerでシェーダーコンパイルしろ!
しろとは言わないけど新しいコンパイラのほうがいいじゃん!やりましょう。
します。
今まではfxc.exeとかc++上ではD3DCompileどうとかみたいな関数でやってましたね。しかしこれではシェーダーの申し子ことメッシュシェーダー先輩やナウいDXR関連のシェーダーとかが扱えなかったりします。そこでDXCompilerの出番です。dxc.exeという名前でたぶんDirectXのSDKとかgithub
にあります。これを使ってdxc.exe ahoshader.hlsl -E bakaEntryPoint ,,,
とすればコンパイルできますがやです。めんどくさいです。
ここで賢いあなたは「VisualStudioが勝手にやってくれないかな~」と思うかもしれませんがやってくれます。優秀さが憎いです。ちなみにその方法は書きません。僕と一緒にC++からコンパイルしましょう。利点としてはシェーダーバイナリにどの情報を含ませるか、とかが柔軟に選べます。ちなみにVisual Studioでしか開発しないなら大したメリットはありません。ではやっていきましょう!
準備
多分あなたのつよつよPCにはDirectX12Ultimateとともにdxc.exeがあるとは思いますがまあそういわずに最新リリースを取りに行きましょう!ここ)
中身はbin
、include
、lib
フォルダがあります。ここでbin
フォルダを見ないでください。なんか便利なexeがいろいろ入っていて(あれ?なんでC++からコンパイルしなくちゃいけないんだ……?)という気持ちになります。そういう気持ちになる前にC++である程度実装してコンコルド効果によって後戻りできない状況を作っておきましょう。
そうしたら'include'フォルダをVSの追加のincludeファイルに入れたり、lib
フォルダを追加のライブラリディレクトリに入れたり、pragma comment
OR追加の依存ファイルにdxcompiler.lib
を入れておきましょう。
先ほどの一文で環境構築の説明は完璧ですね。
実装
とりあえずincludeするもの
#include "dxc/dxcapi.h"//コンパイル関数とかが入っている #include "dxc/DxilContainer/DxilContainer.h"//シェーダーバイナリの中身をいじいじできる
いったん作っておくもの
ComPtr<IDxcUtils> m_pUtils;//便利なオブジェクトをいろいろ作れる ComPtr<IDxcCompiler3> m_pCompiler;//コンパイルする人 ComPtr<IDxcContainerReflection> m_pContainerRefl;//ShaderBinaryの中身をいじいじできる //HRESULT型のチェックもしてるよ。ただこの段階で失敗するのはたぶんメモリが枯れたとかくらいしかないと思うよ。 auto hr = ::DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&m_pUtils)); RETURNIFFAILED(hr); hr = ::DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&m_pCompiler)); RETURNIFFAILED(hr); hr = ::DxcCreateInstance(CLSID_DxcContainerReflection, IID_PPV_ARGS(&m_pContainerRefl)); RETURNIFFAILED(hr);
シェーダーをコンパイルしましょう
HRESULT Compile( const DxcBuffer *pSource, LPCWSTR *pArguments, UINT32 argCount, IDxcIncludeHandler *pIncludeHandler, REFIID riid, LPVOID *ppResult );
まあリファレンスみればわかるのですが直接dxc.exeのコマンドライン引数を指定してる感じです。あとIncludeHandlerとかいう謎存在がいますね。あとpSourceとかはIDxcUtilsとかを使えばファイルから読み込めます。
ではコマンドライン引数から見ていきましょう。
コマンドライン引数について
ここにすべてが書いてます。自分が使ったものだけ書いていきます。
-I /include/dir/
fxc.exeの時はD3DCompileFromFile関数とかでソースファイルからの相対パスでのincludeは標準のIncludeHandlerで勝手にやってくれました。ただdxcではファイルを指定したりしないのでincludeを探すディレクトリは設定しておかなければなりません。なので-I [ソースファイルがあるディレクトリ]
と指定しておくわけです。
ちなみにCompile関数にはLPCWSTRの配列として引数を渡すのですが、-I
[インクルードパス]
というように二つの要素で渡さなければなりません。
-E [EntryPoint], -T [ShaderModel名]
まあ見たまんまですね。EntryPointは指定しないとmainになるとかどっかで見たような気がする。
デバッグ関連
-Zi
: デバッグ情報を含めてビルドする。
というわけなのですがデバッグ情報はシェーダーバイナリに含めるか、外部ファイルに出力するか選べます。含める場合は-Qembed_debug
で、出力するなら-Fd 出力パス名
となります。ところで分けて出力してもらうのはゆとりだと思いませんか?ここはなぜか-Fd
でうまくいかなかったから-Qembed_debug
でコンパイルしたあとデバッグ情報を取り出して手動で保存した僕と一緒にコードを書きましょう。
ちなみに先ほどの文で呆れて読み飛ばした人には内緒ですがなぜか外部にもシェーダーバイナリにもデバッグ情報を置いておかないとPIXでのデバッグができなかったです。たぶん他のやり方はありますがプリパラ見てたら考えるのがめんどくさくなりました。
-Zss
コンパイル情報に(ソースファイルとコンパイルした後のバイナリ)から生成したハッシュを含めます。実はPixでのデバッグに重要になります。
コマンドライン引数を構築するヘルパー関数
これいる?と思いますがまあ。。。うーん。。。別にLPCWSTRの動的配列とかで引数を追加していってもいいし、動的確保がいやなら静的な配列を使ってもいいと思います。まああるので使ってもいいかな、と。特に説明はしませんが使い方はほぼ動的配列みたいなものなのでわかると思います。どうせ実装も動的配列だと踏んでいます。 これ
Include Handler
ComPtr<IDxcIncludeHandler> defaultInc; hr = m_pUtils->CreateDefaultIncludeHandler(defaultInc.ReleaseAndGetAddressOf()); if (FAILED(hr)) { assert(false); return false; }
これでデフォルトのIncludeHandlerを取得できます。これはつまりファイルシステムからインクルードするということらしいです。
カスタムのinclude handlerはあまり調べてないですがIDxcIncludeHandlerを継承して作ればいいらしいです。たぶん作らなくてもいいと思います。
コンパイル結果から情報を取得
hr = m_pCompiler->Compile( &srcBuff, pCmpArgs->GetArguments(), pCmpArgs->GetCount(), defaultInc.Get(), IID_PPV_ARGS(compiledBuff.ReleaseAndGetAddressOf()) );
コンパイルするとcompiledBuffと書いているIDxcResult型の変数に結果が入れられますが、さらにこのResultからIDxcBlobをとってこないといけません。
エラー処理
HRESULT型見れば成功かエラーかくらいわかるでしょ、って感じなんですがS_OKでもエラーになってたりします。その場合はエラー情報がIDxcResultから取得できるので、HRESULT型にキレながら実装しましょう。
ComPtr<IDxcBlobUtf16> outputName{}; ComPtr<IDxcBlob> errBlob{}; hr = compiledBuff->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(errBlob.ReleaseAndGetAddressOf()), outputName.ReleaseAndGetAddressOf());
IDxcResult型から情報を取得するにはGetOutputを使います。DXC_OUT_ERRORS
の部分でどの情報を取得するか決めます。これでerrBlobに中身が入っていたら絶望しながらエラー処理とメッセージの出力をお願いします。
コンパイルした情報を全部取得
ほい
ComPtr<IDxcBlob> compiledShaderBlob{}; hr = compiledBuff->GetResult(compiledShaderBlob.ReleaseAndGetAddressOf()); if (FAILED(hr)) { assert(false); return false; }
コンパイルした情報からいろいろ取得してみる。
pdbファイルを保存
要するにデバッグ用情報ということです。これがないとPIXでシェーダーデバッグしよっかな~、とお散歩に出たら目の前でアセンブラが仁王立ちしている景色に出会います。全裸のアセンブラはさすがに目に毒なのでデバッグ情報を保存しておいてPIXではちゃんと服を着たシェーダーコードを読みましょう。
hr = m_pContainerRefl->Load(compiledShaderBlob.Get()); //pdb名を取得 UINT32 debugNameIndex; hr = m_pContainerRefl->FindFirstPartKind(hlsl::DFCC_ShaderDebugName, &debugNameIndex); ComPtr<IDxcBlob> pPdbName; hr = m_pContainerRefl->GetPartContent(debugNameIndex, pPdbName.ReleaseAndGetAddressOf()); //デバッグ情報の取得 UINT32 debugInfoIndex; hr = m_pContainerRefl->FindFirstPartKind(hlsl::DFCC_ShaderDebugInfoDXIL, &debugInfoIndex); ComPtr<IDxcBlob> pPdb; hr = m_pContainerRefl->GetPartContent(debugInfoIndex, pPdb.ReleaseAndGetAddressOf()); //pdbファイル名の変換 auto pDebugNameData = reinterpret_cast<hlsl::DxilShaderDebugName const*>( pPdbName->GetBufferPointer()); auto pName = reinterpret_cast<char const*>(pDebugNameData + 1);
基本的にIDxcContainerReflectionにバイナリ情報を読ませて、FindFirstPartKindで情報がどこにあるかを探す。GetPartContentで情報を取得。という流れです。
コードではpdbファイルの名前とその中身を取得しています。pdbファイルは後でPIXに読ませるのでファイルとして保存しておきましょう。
ファイル名を取得
ファイル名まで無効に決められると俺に指図するな!と言いたくなりますが、そうしたらPIXがへそを曲げてpdbファイルを自動で呼んでくれなくなるので権威には逆らわずに生きていきましょう。
取得方法はコードを読んでの通りですが、この名前は先のZss引数で生成されたハッシュ値となっています。
ファイルを保存してPIXにパスを設定
さっきの名前を使ってデバッグ情報をpdbファイルとして雑な場所に保存します。この場所をPIXに教えてあげます。PIXの左上のHomeを押してSettings>Symbol/PDB Options>PDBSearch Pathsです。そこに保存先のpdbがあるディレクトリを教えてあげるのです。
これでPIXが勝手にpdbファイルを読んでくれます。
問題点
pdbのファイル名がハッシュ値なので更新のしようがありません。ソースファイルを変えるたびに違ったハッシュ値が生成されるのでそのたびに違う名前のpdbファイルが増えていきます。古いpdbファイルを消したいんですけどどれが消すべきファイルなのかわからないんですよねー。
幸いただのデバッグ用ファイルなのでめちゃくちゃ多くなったら消すくらいでいいと思います。本気で参照されないpdbを消すようにするなら以下の二通りでしょうか。
まあ使わないpdbがあってもいいんですけど、公式のドキュメントにはそれとは別に「いっぱいpdbがあったらさがすのに時間かかっちゃうよ~;;!ふぇぇぇぇ~」と書いています。公式ドキュメント幼女。そういう場合はpdbファイルをzipにまとめてしまうのがいいとか。PIXが気合でzipから読みだすらしいです。
あとpdbファイルを保存した後にデバッグ情報をバイナリから削除することができるのですが、
//pdbを除いた情報を生成 ComPtr<IDxcContainerBuilder> pDxcContainerBuilder; ::DxcCreateInstance(CLSID_DxcContainerBuilder, IID_PPV_ARGS(pDxcContainerBuilder.ReleaseAndGetAddressOf())); pDxcContainerBuilder->Load(compiledShaderBlob.Get()); #if defined(NDEBUG) pDxcContainerBuilder->RemovePart(hlsl::DFCC_ShaderDebugInfoDXIL); #endif // !defined(_DEBUG)|| defined(DEBUG) ComPtr<IDxcOperationResult> pstrippedResult; pDxcContainerBuilder->SerializeContainer(pstrippedResult.ReleaseAndGetAddressOf()); pstrippedResult->GetResult((IDxcBlob**)&pcompiledShaderObj);
これを行うとなんかシェーダーのステップ実行ができなくなります。なんででしょうね。どちらかにデバッグ情報があれば十分なはずなんですけどね。そういうわけでShaderDebugInfoを消す部分はRelease版だけ行うことにしています。そもそもRelease版だとコンパイルの時点からデバッグ情報を持たせなければいいのですけど。
これでPIXでのデバッグができます。世の中の内製開発環境や大してサポートされていないような環境では割とシェーダーのステップ実行ができなかったり、シェーダーコードがアセンブラになってしまう症状は起きうるのですが、これを見るにpdbファイルかシェーダーバイナリ内のデバッグ情報が欠けているということですね。なるほどです。
シェーダーリフレクションを取得
//shader reflectionの取得 auto hr = m_pContainerRefl->Load(pcompiledShaderObj); UINT shdIdx = 0; hr = m_pContainerRefl->FindFirstPartKind(DXC_PART_DXIL, &shdIdx); hr = m_pContainerRefl->GetPartReflection(shdIdx, IID_PPV_ARGS(_ppRflc));
このコードではID3D12ShaderReflection** _ppRflc
にシェーダーリフレクションを取得しています。シェーダーリフレクションはシェーダーのソースバインド情報とかが取得できます。僕のライブラリだとシェーダーリフレクション情報をもとにID3D12Resourceとかそのあたりを自動生成しているのでこれがなくなると終わりです。
ちなみにシェーダーリフレクション情報もシェーダーバイナリから削除することができます。もったいないぃぃ。
おしまい
誰もdxcompiler.libとかc++からコンパイルしていなかったのでよっぽど需要がないのだな、と思い誰からも読まれる心配がないので雑に書くことができました。個人的にはすでにD3DCompileFromFile関数を使ってシェーダーコンパイラークラスを実装していたのでその代替処理としてdxcでもc++からコンパイルしたかったのが動機です。
あとECSがどうこうと言っていましたが、どうせECSは仕事やってるうちに勉強する機会がありそうだったのでMeshShaderでの描画についてやっていきます。