投稿記事

無料プランの記事 (168)

Heliodor 2021/07/29 20:40

制作近況

バイクで信号待ちしていたら、前の車が待ち時間にリアウインドウの汚れ(めっちゃ汚れてた)を落とそうと思ったらしくウォッシャー液を噴射していて、一部がぷしゃーとこっちに飛んできてズブ濡れになりました。夏でよかった……よくない。
大げさにリアクションしながらクラクション鳴らしたら止めてくれましたが、信号が変わったとたんにすごい勢いで走り去っていきました。ヤバい人と思われたんでしょうか。ヘリオドールです!(挨拶)。




最近はひたすら地味な作業が続いています。

作業がゲーム後半部分になりつつあるので、あんまりお見せできる成果が無いのですが、毎日コツコツ進めています。

女性キャラはブルマーが描けるんで平常心(?)で無限に作業が続けられるのですが、敵キャラとか男キャラとかずっと描いていると病んでくるので気分転換にローテしながら描いています。多分とても効率が悪い。





それはさておき、寝っ転がっていると脳の計算性能が低下するような気がしませんか?

仰向けとか右向き左向きでも脳の性能が変化するような?

一部低下する代わりに何かが上がっているのを期待してゴロゴロしているのですが、ただサボっているだけに見えないことも無いような有るような。





結局のところ横になっての作業は効率が悪―――――スヤァ










と思ったら、たまーに何かを閃いたりするので油断できません。しかもワリと重要なやつ。


そんなことないですか?……ないですか。








その昔、逆立ちやブリッジでアイデアを出すガキ大将がおってな。




フォロワー特典はなんとなく描いたステージ3ボスの絵です。

フォロワー以上限定無料

まずは無料プランで様子見を。 お気軽にフォローしてみて下さい。

無料

【 500円 】プラン以上限定 支援額:500円

このバックナンバーを購入すると、このプランの2021/07に投稿された限定特典を閲覧できます。 バックナンバーとは?

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Heliodor 2021/07/23 12:45

少しだけ詳しく水たまりプログラム説明 その6

最近ちょっといいことから悲しいことまで、色々あって更に暑さでグッタリしていました、ヘリオドールです(挨拶)。



というワケで少しだけ詳しく水たまりプログラム説明 その5の続きです。
とうとう最終回です。無駄に長かった。


前回の記事でピクセルシェーダーに手を出して世界が変わったわけですが、ここで念願だったス〇ラトゥーンもどきをやってみます。
とりあえずプレイヤーが歩いた後にバシャバシャと液体がばらまかれるわけですが、きちんと水の飛び散りを計算して……とか面倒なことはやらずに、テクスチャでごまかします。


こんなテクスチャを用意しまして、プレイヤーが移動するごとにランダムで1枚のしぶきを、ランダム角度、ランダムサイズでマスクテクスチャに書きこみます。

マスクテクスチャとは、水深をグレースケールで表した画像で、これによって水のある場所と無い場所を表すことができます。
1.0(白)ならば水がある、0.0(黒)ならば水が無いといった具合です。

これは、波の高さに対する乗算マスクと考えてもかまいません。計算の結果波が高くなったとしても、水深 0.0 で乗算すると波の高さも 0.0 になるので、それ以上外側に波が広がらなくなる、という理屈です。


で、とりえあずどんなマスクテクスチャができるかといいますとこんな感じです。
※動画が横長なので全画面表示推奨

ちなみに左上のテクスチャーが無加工のマスクで、左下はところどころぼかす処理を入れたものです。

場所によってが輪郭のハッキリしていたり、ぼやけていたりしていますね。
これは適当な2次元のパーリンノイズを参照して、ノイズの白の部分だけをぼかす みたいにしてやっています。


パーリンノイズというのはこういうヤツです。CGツールでよくある雲模様ですね。

ちなみにこの画像を生成するのには stb_perlin.h にお世話になりました。
https://github.com/nothings/stb/blob/master/stb_perlin.h





……で、あやかし紅白戦では使う予定はありませんが、ここまできたら色も変えられるようにしたいですよね。将来気が変わって使うかもしれんし。

というわけで、プレイヤーの状態に応じて異なる色の液体をばらまくようにしてみました

無理矢理1つの画面に収めたので見にくいのですが、左側にある3個のテクスチャの一番上が色選択用のテクスチャです。
色の違いは波の計算には一切影響せず、描画するときにだけ利用する感じです。


この色用テクスチャにも1フレームごとにシェーダーを適用していて、だんだん隣接する色と混ざりあうようにしています。

まあたくさん混ざるとどんどん黒くなっていって汚くなるのですが……望まない形でリアルな挙動になりましたね。



真ん中のテクスチャーは水として計算する領域を表しています(この記事の最初の方で既出のヤツです)

で、一番下のテクスチャーが波の計算結果です。
Rチャンネルが水面の高さ、
Gチャンネルが水面の速度(上昇または下降)、
Bチャンネルが水面の傾き(X方向、Y方向の傾きの平均値)を表しています




正直、一番最初に考えていたモノよりもずっとそれっぽいモノができた気がします。


リアルタイムでこんなに白濁液まみれになるゲームって結構珍しいんじゃないかな?と満足しています。……まあ探せばありそうな気もしますがw

1件のチップが贈られています

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Heliodor 2021/07/06 20:37

雑談

どうでも良い話です。
買い物自慢話。





特に使い道は無いけど、なんとなく欲しかった小さいノートパソコン(UMPC)を買っちゃいました。ヘリオドールです(挨拶)。



実は私の大好きなドンキPCにも19,800円のUMPC(NANOTE)があったのですが、これは気が付いた時には既に売り切れてました。ぬかったわ……。

そして少し前に後継機(NANOTE P8)が出たのですが、お値段がなんと一万円アップして29,800円(税込み32,780円)になってしまい、喉から出ていた触手も引っ込みました。さすがにねぇ……。


それでも一度UMPCが欲しくなってしまった気持ちは収まらず、観念してNANOTE P8を買うか、中古でONE MIXとかGPDを買うか……と悩んでいたのですが、Amazonで39,800円でよさげなUMPCを発見。もちろん新品。

製品名がFFF?(商品名にみっちりスペックが書き込まれててよく分からんヤツ)そしてメーカー名も聞いたことない名前でしたが、今時のUMPCはだいたい全部中華製ですし「まあいいか」と購入。

ここはストレージ容量重視で! あとCPUパワーもちょっとだけNANOTE P8より高いし!








届いた実物の写真がコレ。


小さいですねー。1/144サイズのガンプラと並べてもこの小ささ。
白っぽく光るキーボードバックライトがカッコイイ。寝床で使う時に便利そう。



サイズはだいたいDVDケースと同じぐらい?


その辺にあった初音ミクの箱と比較。少し小さくて厚みがある感じ。
モニターは180度回転してタブレットモードにもなります。もちろんFHDタッチ液晶。こんな厚みがあるものをタブレットと呼ぶのも無理がある気がしますが。




いつもの14インチのドンキPC(MUGA 3)と並べるとこのサイズ差ですよ。
これなら気軽にカバンに入れて持ち運べますね。筐体も金属製で人を殴rとても頑丈そうです。




今気が付いたんですけど、キー自体の大きさはあんまり変わらないんですね。
……右端辺りは配置も大きさもエラいことになってますが。
EnterまでFnキーとの組み合わせがある狂気!!




しかしあまりにもモニターが小さ過ぎて見辛いので外部モニターを接続。
あと、使い辛いポインティングデバイスとキーボードも追加。

いやー、UMPC小さくて便利ですね!(※ツッコミ禁止)







おまけ1

なんか今見たらAmazon値上がりしてました。(39,800円→53,771円)
……勝ったな!





おまけ2

Windows11の動作最低環境
9型以上で8bitカラーの720pディスプレイ以上」って
どういうことだよMicrosoftォォ!?
(※今回購入したノートPCは8インチモニター)
敗北……か……。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Heliodor 2021/06/30 19:08

謎の光

今回は一応、製作関係の話なのでフォロワー以上で。

フォロワー以上限定無料

まずは無料プランで様子見を。 お気軽にフォローしてみて下さい。

無料

【 500円 】プラン以上限定 支援額:500円

このバックナンバーを購入すると、このプランの2021/06に投稿された限定特典を閲覧できます。 バックナンバーとは?

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Heliodor 2021/06/18 19:30

少しだけ詳しく水たまりプログラム説明 その5

「暫く人と会わんし」とニンニク一気食いしておかしくなっていた味覚がようやく元に戻ってきました。
なんかまだ胃の調子がおかしい気がしますがまたニンニクたくさん買ってきます、ヘリオドールです(挨拶)。



少し間が空いてしまいましたが少しだけ詳しく水たまりプログラム説明 その4の続きです。

とうとうピクセルシェーダーに手を出します。
……そう、私は今まで水面計算においては色々あってGPUの力をほとんど借りてこなかったんです。

水面計算をするには、水面上に格子を割り当てて、格子の各交点に当たる部分(質点)についての上下運動を計算していました。


前回のこんなの。

・格子状に並んだ大量の質点の計算
・一つの質点に影響するのはそれに隣接する質点だけ
・全く同じ計算式を全ての質点に対して実行する

それってまさにピクセルシェーダーでやる事ではないですか。
もう腹を括ってやるしかない!!


ピクセルシェーダーで処理するということは、チマチマとポリゴンメッシュを作る必要は無くなります。
例えば今までは 64x64 個の質点が並んだ水面格子を処理したい場合はそのまま 64x64 個の頂点からなるポリゴンメッシュを作り、各頂点を計算する必要がありました。

しかしシェーダーで処理すれば、テクスチャの1ピクセルがそのまま1質点に対応することになるので、64x64ピクセルのテクスチャを処理すれば良い、ということになります。
こうして計算して出来上がった水面画像を、たったの4頂点から成る四角形ポリゴン(1枚!)に貼り付れば良いだけです。


話が劇的に単純になりましたね!
この方法なら 1024x1024 とか 2048x2048とかの膨大な量の質点の計算も無限のGPUパゥワァァァァーで簡単にできます。多分。



問題はどうやって質点情報をテクスチャに落とし込むかという事なんですが、まずは質点の情報を保持するためだけの計算用テクスチャを用意します。

計算用といってもテクスチャであることに変わりはありませんから、一つの点で保持できるのはRGBAの4つの数値です。
そのままいつものように D3DFMT_R8G8B8A8 とかでテクスチャを作ってしまうと、RGBA を各 0~255 の整数でしか扱えない(1質点につき0~255の整数が4個だけ使える)ことになります。
つまり、次のような構造体で1質点を表すということ。


struct Pixel {
	BYTE r;
	BYTE g;
	BYTE b;
	BYTE a;
};

う、うーん……これではさすがに無理があるので、浮動小数テクスチャ D3DFMT_A32B32G32R32 を使って1点につき4個の実数が使えるようにしましょう。


struct Pixel {
	float r;
	float g;
	float b
	float a;
};

本来ならば r, g, b, a には色の値を入れますが、そんな事は完全に無視して、自分が入れておきたい値を勝手に入れることにします。今回の用途でいえば、r, g, b には位置(高度)、加速、傾きを割り当てることにします。a は使いません。

つまり

struct Pixel {
	float pos; // 高さ
	float accel; // 加速度
	float tangent; // 傾き(x方向と y方向の傾きの平均値を入れるものとする)
	float not_used;
};

と定義するのと同じことです。


さて、このテクスチャに適当な初期値を画像として設定して処理させると水面ができるわけですが、ここで問題になるのは、テクスチャはただの四角系だということです。水面はもっと複雑な形をして欲しい。

というわけで、もう一枚同じサイズのテクスチャを用意して「形状定義用」として使うことにします。マスクと呼んでもよいかもしれません。

このマスクテクスチャは、質点がどのぐらいの範囲で動けるか、という範囲情報を 0.0~1.0 の値で持ちます。0.0 だと、そこの質点は全く運動を許されていない、1.0だと最大の上下運動ができるという具合です。

これが何の意味を持つのかということですけど、この 0.0 を地面、1.0 を水面とみなすと、水面の形を定義するのにちょうどよいんです。
これで水面の形に依存した波をシミュレートすることができます。
(水面の形に依存した波…というのは具体的には、水面の端で波が反射したり、
狭い通路を波が通過した場合はその出口を中心として再び波が広がるといった、まさに波の性質で習ったような動きです)

結果、こんなシェーダーになりました(抜粋)。





uniform float2 TextureSize; // テクスチャサイズ
uniform texture CalcTexture; // 前回の計算結果テクスチャ
uniform texture MaskTexture; // 波が活動できる範囲。ピクセルごとの質点の上下移動可能範囲を明度で表したもの。0(=黒) だとそこの質点は一切上下運動しない
uniform int Pull = 0; // 引っ張る?(波の発生)
uniform float2 PullPos = {0, 0}; // どこを引っ張る?(uv)
uniform float TimeDelta = 0.2;
uniform float WaveSpeedK = 0.2; // 上下差から速度への変換係数
uniform float WaterRestoreK = 0.01; // 変位 0 に戻ろうとする力(発散防止のため)
uniform float MaxSpeed = 2.0; // 上下運動の速度制限
uniform float MaxPos = 20.0; // 上下位置制限

sampler calc_sampler = sampler_state { // 計算結果テクスチャ
	Texture = <CalcTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
	AddressU  = Clamp;
	AddressV  = Clamp;
};
sampler mask_sampler = sampler_state { // 形状テクスチャ
	Texture = <MaskTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
	AddressU  = Clamp;
	AddressV  = Clamp;
};

// 質点
struct Dot {
	float pos; // 質点の高さ
	float vel; // 質点の速度
	float tan; // 質点における傾き
};
Dot dot_decode(float4 v) { // RGBを質点情報に変換
	Dot dot;
	dot.pos = v.r;
	dot.vel = v.g;
	dot.tan = v.b;
	return dot;
}
float4 dot_encode(Dot dot) { // 質点情報をRGBAに変換
	return float4(
		dot.pos, 
		dot.vel,
		dot.tan,
		1.0
	);
}
float4 ps(float2 uv: TEXCOORD): COLOR {
	Dot dot0 = dot_decode(tex2D(calc_sampler, uv));

	// 質点の速度(高さ方向)を更新
	{
		float spanU = 1.0 / TextureSize.x; // 左右隣の点との距離(UV単位)
		float spanV = 1.0 / TextureSize.y; // 上下隣の点との距離(UV単位)
		Dot dotL = dot_decode(tex2D(calc_sampler, float2(uv.x-spanU, uv.y))); // 左の点
		Dot dotR = dot_decode(tex2D(calc_sampler, float2(uv.x+spanU, uv.y))); // 右の点
		Dot dotU = dot_decode(tex2D(calc_sampler, float2(uv.x, uv.y-spanV))); // 上の点
		Dot dotD = dot_decode(tex2D(calc_sampler, float2(uv.x, uv.y+spanV))); // 下の点

		// 隣接点との高低差に応じて速度を決定
		dot0.vel += (dotL.pos - dot0.pos) * WaveSpeedK;
		dot0.vel += (dotR.pos - dot0.pos) * WaveSpeedK;
		dot0.vel += (dotU.pos - dot0.pos) * WaveSpeedK;
		dot0.vel += (dotD.pos - dot0.pos) * WaveSpeedK;
		dot0.vel = clamp(dot0.vel, -MaxSpeed, MaxSpeed); // 速度リミットを適用

		// 質点の傾き平均
		float tanX = dotR.pos - dotL.pos;
		float tanY = dotD.pos - dotU.pos;
		dot0.tan = (tanX + tanY) * 0.5;
	}

	// 質点の高度を更新
	{
		dot0.pos += dot0.vel * TimeDelta; // とりあえず現在の速度をそのまま適用する
		dot0.pos += (0.0 - dot0.pos) * WaterRestoreK; // 発散防止のため、常に 0 に戻るよう補正しておく

		float maxpos = MaxPos * tex2D(mask_sampler, uv).r;
		dot0.pos = clamp(dot0.pos, -maxpos, maxpos); // 高度制限を適用
	}

	// Pull に 1 が指定された場合は PullPos で指定された場所をぐいっと盛り上げる(波を発生させる)
	if (Pull) {
		float2 delta = PullPos - uv;
		if (length(delta) < 0.01) {
			dot0.pos = MaxPos;
		}
	}

	
	float4 color = dot_encode(dot0);
	color.a = tex2D(mask_sampler, uv).r; // 形状マスクの値をアルファに入れておく(後で水面を描画するときに役に立つ)
	return color;
}

プログラム側で準備するのは3枚のテクスチャーで、サイズはすべて同じにしておきます。

・液体範囲設定用のマスクテクスチャー (A)
グレースケールの不透明テクスチャで、水面として使いたい範囲を白く塗ったもの。
水面以外は真っ黒。面倒な場合は全面白のテクスチャーでもOK

・計算用のレンダーテクスチャー(浮動小数フォーマット)二枚 (B, C)
・計算用のシェーダー(上で説明したヤツ)


シェーダーをセットして MaskTextuxre に A を、CalcTexture に B を、レンダーターゲットとして C を設定します。
この時、波を発生させたい場所を PullPos にセットして Pull=1 にすると、その場所がボコっと盛り上がります。
これで描画すると、テクスチャ C には B から 1 tick だけ時間を進めたものが入っているので、これを適当に画面に描画します。

最後に std::swap(B, C) でBCを入れ替えることで、テクスチャの入力と出力を入れ替えます。
あとはこれを繰り返し実行していけば、いい感じで波が広がります。


https://twitter.com/helio_dor/status/1360194732270395394
これは描画方法だけ変えたものを3個横に並べています。

左は、計算結果の値をそのままRGBに対応させて描画。
なので、0.0 と 1.0 の中間である 0.5 が水面の高さという扱いになっています。
水面が高くなれば 1.0 に近づき、波が全くない場所では 0.5 に、水面が低くなったら 0.0 という具合です。
そのため、初期状態では R=0.5 G=0.5 B=0.5 の灰色になっています。


中央は、計算結果の傾き情報を利用して背景をゆがませたもの。
右は、計算結果の高さと傾きを利用して陰影をつけたものと、範囲設定用のマスクテクスチャーを合成したものです。
動画だとちょっと見づらいのですが、ちゃんと水際で反射したり、狭い通路に波が入り込んだりしているのがわかるでしょうか?


これの良いところは、マスクテクスチャにいくらでも好きな形の水面を書いておくことができるということです。
それはつまり、なにもあらかじめマスク画像(水面の形状画像)を用意しておかなくても、マスクテクスチャにリアルタイムで値を書き込んでいけば、その場でどんどん形を変えられるということですよ。


さあ、ここまでできればあとはやりたい放題ですよ!
たとえばこんな感じ。


詳細は次回書きますが、キャラクターの場所にどんどん生成されている灰色部分がマスクテクスチャに書き込まれた絵です。
(これは単に、レンダーターゲットとして指定したマスクテクスチャに対して、あらかじめ用意しておいた飛沫画像を追加描画しているだけです)

そして灰色領域のなかで、虹色の波が広がっていますね。
これをちゃんとした色で描画すれば、いい感じに波紋が広がる白濁液に見えるはず……!!




そしてまた つづく










おまけ

なんか新しいWindowsのISO(Windows11?)が流出したとかナントカ。

少し前にWindows10のサポートを2024年で打ち切るという発表があったので、やっぱりそうなのかとも思いましたが、今のところは真偽不明。一応ね。

個人的に一番気になったのは問題のISO、インストールにはTPM 2.0が必須……つまりIvy Bridge(第3世代)以前のPCは対応していないんだとか。


やってくれた喃……Microsoft!





Sandy Bridge(第2世代)は切り捨てか……。
やっぱりそろそろ新しいPC組むかなぁ。


この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

1 2 3 4 5 6 7

限定特典から探す

記事のタグから探す

月別アーカイブ

記事を検索