旅行しながら働く ムラサメ研究所社長ブログ

主にゲームやプログラミングのログ

良い情報を発信していきたいので、寄付頂ければ幸いです

BTC 13JpgsF3n6K2WhjEeUuUUqS7V71gWdFx56
BCH 18q6rfi9ynyTgynrB8tJ2eSDLPQM32RZk5
ETH 0x00afa2f16a062450ebedb7e3cabe79cc7801a231
NEM NAJOM3CD26UI3CF4LUCWLN2QJEHGFFJZ7AHLRAOQ
Shield SbrJFMavwAx2y6S7kLnxZLDgqrgjBYMVU4
MONA MPpuEnmqDYBCxSZyG5cBDt6UWtXczmRmkn

作っているOSSメモ - 旅行しながら働く ムラサメ研究所社長ブログ

UNITYで影をつくる〜アクネ退治

先程 酷いアクネを出していました

f:id:murasame-labo:20180919203509p:plain

アクネというのはニキビという意味ですが、3DCGでは上記のようなゴミが出ることをいいます
上記は、影でよく出る種の デプスバッファの量子化におけるアクネではないのですが
似ているのでアクネといってみます

原因は、実は ShadowCasterにて、Posしか計算していなかったのが理由で
今回は
TRANSFER_SHADOW_CASTER_NORMALOFFSET
を使うようにします

ShadowCasterパスを直します

構造体

まず 今までは 頂点、ピクセル座標しか入力してなかったのを、色々と

頂点シェーダの入力

appdata_base構造体を使います
中身は

            struct appdata_base {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

と、頂点、法線、UVがあります

フラグメントシェーダの入力

             struct v2f {
                V2F_SHADOW_CASTER;
            };

とUNITYのマクロを使いますが、DirectionalLightだと下記のように posのみです

             struct v2f {
                float4 pos : SV_POSITION;
            };

TRANSFER_SHADOW_CASTER_NORMALOFFSET

UnityObjectToClipPosから変更

                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)

結果

アクネなくなった
f:id:murasame-labo:20180919205513p:plain

UNITYの影 LIGHT_ATTENUATIONは SHADOW_ATTENUATIONを乗算している

#ifdef DIRECTIONAL
#define DECLARE_LIGHT_COORDS(idx)
#define COMPUTE_LIGHT_COORDS(a)
#define LIGHT_ATTENUATION(a) SHADOW_ATTENUATION(a)
#endif

上記はDirectionalだが、他のライトも同じで、LIGHT_ATTENUATIONには影が乗算されている

UNITYで影を受け取る

前回は影を落としましたがまだこのシェーダでは影を受け取れません
地面(Plane)メッシュのシェーダーを 今使ってる yUnitに変えると影はおちないし、セルフシャドウもありません
今回は影を受け取るようにします

https://github.com/YukiMiyatake/UnityLesson/tree/Shadow_2github.com

仕組み

UNITYではシャドウマップを使っています
シャドウマップの具体的な説明は他のサイトにお願いして
ライトからみたデプス値を事前に別のテクスチャに書き込んでおきます
レンダリング時に、ライトからみたデプス値と比較をして、ライトのほうが近い場合は、そのポイントは影になる
という仕組みです
その ライトからみたデプステクスチャを作るパスが、前回つくった ShadowCasterパスになります

今度は、そのデプステクスチャを参照して影を作るのですが
以前のUNITYではShadowReceiveパスで影を処理していたようですが、今は通常のカラーパスにて行うことができます
具体的には、SHADOW_ATTENUATIONマクロを使えば、影は0、表は1で、その間を補完した値が手に入ります
ので そのままカラーに乗算すれば影は黒くなります

pragma

今回は ShadowのON/OFFがあるので、その両方のシェーダをコンパイルする必要があるので下記のpragmaが必要です
本当は 各種ライトに対するシェーダも必要なので もっとたくさん必要ですが、今回は最低限

#pragma multi_compile_fwdbase

構造体

フラグメントシェーダにて SHADOW_ATTENUATIONマクロを使いますが、そのために必要な入力値があるので追加
v2fにSHADOW_COORDS(n) を追加し、影用のテクスチャを追加します。今回はテクスチャ2番まで使ったので3を割り当て
あと、私が少しハマったのが、ポジションを posという名前にしなければ計算できないようです・・・
ので 以前 vertexとしていたメンバ名を posに変える

影の取得

SHADOW_ATTENUATIONに、入力構造体の中身を渡せば 0.0~1.0の範囲で取得できます
今回は単純にそれをdiffuseに乗算します

             float3 diffuse = (NdotL*0.5 + 0.5) * lightCol * SHADOW_ATTENUATION(i);

完成コード(ForwardBaseパスのみ)

     Pass{
            Tags{
                "LightMode" = "ForwardBase"
            }

            Cull Back

            CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag

           #include "UnityCG.cginc"
           #include "Lighting.cginc"
           #include "AutoLight.cginc"
                         #pragma multi_compile_fwdbase

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 texcoord   : TEXCOORD0;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float4 vertexW: TEXCOORD0;
                float2 uv     : TEXCOORD1;
                float3 normalWorld : TEXCOORD2;
                SHADOW_COORDS(3)
            };

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform float _Spec1Power;
            uniform float4 _Spec1Color;


            v2f vert(appdata_full v){
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.vertexW = mul(unity_ObjectToWorld, v.vertex);

                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.normalWorld = UnityObjectToWorldNormal(v.normal);

                half3 eyeVec = normalize(o.vertexW.xyz - _WorldSpaceCameraPos);

                TRANSFER_SHADOW(o);

                return o;
            }

            float4 frag(v2f i) : SV_Target{
                float3 L = normalize(_WorldSpaceLightPos0.xyz);
                float3 V = normalize(_WorldSpaceCameraPos - i.vertexW.xyz);
                float3 N = i.normalWorld;
                float3 H = normalize(L + V);


                //LightColor
                float3 lightCol = _LightColor0.rgb * LIGHT_ATTENUATION(i);

                //Ambient
                float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                // texture albedo
                float4 tex = tex2D(_MainTex, i.uv);

                // Diffuse(HalfLambert)
                float3 NdotL = dot(N, L);
                float3 diffuse = (NdotL*0.5 + 0.5) * lightCol * SHADOW_ATTENUATION(i);
                // Speculer
            // float3 specular = pow(max(0.0, dot(reflect(-L, N), V)), _Spec1Power) * _Spec1Color.xyz;  // reflection
                float3 specular = pow(max(0.0, dot(H, N)), _Spec1Power) * _Spec1Color.xyz * lightCol;  // Half vector

                return float4( (ambient + diffuse) * tex + specular, 1.0);
            }
            ENDCG
        }

f:id:murasame-labo:20180919185417p:plain

影ができた(でもアクネがあるね)

UNITYで影をつくる〜ShadowCaster

UNITYでは簡単に影を落とせます
具体的には ShadowCasterパスにて

 #include "UnityStandardShadow.cginc"

とするだけです
CUBEMAPや各種設定に対応するため 上記の用意されたものを呼ぶ
あるいは その中身をみて ビルトイン関数を使うべきですが
勉強のために ビルトイン関数を呼ばずに影を作ってみます

コードはこちら

github.com

影の設定

UNITYでは影のON/OFFは MeshRendererの設定から行う

f:id:murasame-labo:20180909021251p:plain

UNITYでは
ShadowCasterパスでシャドウマップに書き込み
ShadowRecieveパスで影を描画していましたが
いつからか ShadowRecieveパスがなくなり(効率化!)
SHADOW_ATTENUATION として、通常のレンダリングパスで影を取得出来るようになりました

ShadowCaster

上記のincludeを使わず自力で行ってみます
ShadowCasterパスをつくり、そこに下記のコードを

        Pass {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }

            ZWrite On ZTest LEqual

            CGPROGRAM
            #pragma target 3.0

  
            #pragma vertex vertShadowCaster
            #pragma fragment fragShadowCaster


            struct VertexInput {
                float4 vertex : POSITION;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION ;
            };

            VertexOutput vertShadowCaster (VertexInput v) {

                VertexOutput o = (VertexOutput)0;
                o.pos = UnityObjectToClipPos( v.vertex );
                return o;
            }

            float4 fragShadowCaster(VertexOutput i) : SV_TARGET {
                return 0;
            }


            ENDCG

        }

基本的に ShadowCasterパスでは色は関係ないようです
Zバッファに書き込むだけでよさそう
影のZファイティングを避けるため LEqualを使います

これで地面に影が出るはずです

UNITYちゃんトゥーンシェーダー2.0(UTS2.0)を調査

UNITYちゃんトゥーンシェーダーとは

現ユニティーテクノロジー ジャパンの小林さんの作ったトゥーンシェーダー
元々映像用に作ってあり かなり立地な表現が可能
GGXrdのトゥーンシェーダーがすごく、それを再現したようなシェーダー
今は更に機能が追加されている

ただ、映像用なのでリアルタイムで使うには少し重いかもしれない

ユニティちゃんトゥーンシェーダー2.0 - ダウンロード - UNITY-CHAN! OFFICIAL WEBSITE

シェーダーが多い

シェーダーファイルにして58本と非常に多いが
法則性があるので怖くない

ライブラリ

まず ライブラリとして使われているものは4つ
UCTSで始まるものだ

UCTS_DoubleShadeWithFeather.cginc
通常のライト計算

UCTS_ShadingGradeMap.cginc
後に出てくる GradeMap用のライト計算

UCTS_Outline.cginc
アウトライン

UCTS_ShadowCaster.cginc

通常シェーダ

Toon_DoubleShadeで始まるもの
通常のトゥーンシェーダにアウトライン付き
通常はこれを使うといい
いっぱいシェーダがあるが それも法則性があるので大丈夫

GradeMap系シェーダ

Toon_ShadingGradeMapで始まるもの
こちらもアウトライン付きだが、陰のかかりやすさをテクスチャで設定可能な
よりリッチなシェーダ
服のシワとかを出すのに便利らしい

ToonColor系シェーダ

アウトラインがないもの

Mobileシェーダ

処理が軽くなった(設定項目も減った)シェーダ

Stencil系シェーダ

髪から目を透過したりする時に使う
透過するもの(髪)には StencilOut系のシェーダを使い
表示するもの(目)には StencilMask系のシェーダを使う

Clipping系シェーダ

髪の毛の先等の透過をする時に使うシェーダ
TransClippingだとテクスチャのアルファ情報を使い透過してくれる

貯金が趣味?蓄財? いいえ、人生の経費節減です

趣味は何ですか?

と言われると非常に困る
旅行が趣味の友達は、旅行がないと生きていけないといった(実際は生きていけるだろうけど)
音楽が趣味の知り合いは、時間があれば練習して何年もライブしている
釣りが趣味なおじさんも、釣り用の車を買い時間あれば釣りにいっている

私は色々な事をしているし、最近色々な趣味を始めた
海外旅行を毎月いくというのを3年間 だいたい達成したし
音楽や釣り、過去においては コスプレや衣装作成、各種スポーツ、テーブルゲーム・・・
色々と手を出したが
たいていの趣味は楽しいが、本当にないと死ぬと思うのは

プログラム だけである。ってこれ仕事だよね。

次点では
ゲーム、美味しい食べ物、お茶・・・ などがある

が、総括して出てきた答えは

趣味は貯金です

と答えることにした
面倒だから

本当は貯金なんて大嫌いだ。理由は明白
超低金利時代、利息なんてほとんど無い。倒産リスクだけ背負う
ただし、タンス貯金とリスクがどちらが高いか? と言われれば メガバンクの方が安全だと思う
だから銀行に貯金している
ただし、そもそも 日本円全てに賭けるギャンブルは リスクヘッジの側面としては最悪だ
1ドル80円台の円高時代からみると今は 3割以上目減りしている
だから 貯金は嫌いです!!

蓄財が趣味

円貯金、株や外貨、外国株、リート、債券、Gold、仮想通貨・・・  と リスクヘッジのために色々と分散しているので
正しくは趣味は貯金ではなく蓄財か?

アーリーリタイアしたい

いや・・お金貯めたところで、死ねば終わり
お金を貯め仕事をリタイアし、あとは趣味のゲーム三昧
ってのが私の理想

ただし、人間が生きていくためのお金というのは幅が広い
日本で暮らすことを考える。とりあえずあまり外的要因増やしたくないので 年金は入らない計算で
現在では田舎だと年間100万円あれば最低限の生活が可能だが、もう少し美味しいもの食べたいなら 200-300万
それに あと何年生きていたいかを掛ければ 必要経費が出てくる
仮に40年とするなら 1億程度
それに 3割のセーフティーマージンを加えて 1億3千万 とか計算していく
もちろん、都心部で住みたいならこれに何割かプラスする必要がある

ところが、もし日本の物価が大きく変動する可能性があるので
このマージンでは足りないかもしれない
保険料負担も増えるかもしれないし
等と考えると マージンを2倍にして 2億以上欲しい

って考えると一生働かなければ不安だ
引退が出来ない・・・

計算式は (年間家賃x物価+年間食費x物価+年間交際費x物価+・・・)x 生きる年数 x マージン
不特定な係数だらけだ・・・

もちろん、お金が足りなくなれば バイトする、さらに田舎に住む、生活レベルを下げる、海外移住、死を選ぶ
という選択肢もあり
実際私は 死を選んでもいいと思ってる
だが これは理想的な計算式ではない
不確定な係数が多いからだ

不確定な変数を減らす&小さくする

上記の変数を減らせば計算の精度が増す 具体的にいえば

生活のランニングコストを下げる

寿命を気にしなくする

最も影響力の大きい 生きる年数という変数は消せない
ので、そこは仕方がないので、何歳で死ぬかを決める。
その上で、予定をオーバーしても生きたいなら生きらえることに投資をする
例えば健康であれば必要経費も減るしバイトも出来る
甥っ子や姪っ子に投資して彼らの収入が上がれば面倒見てくれるかもしれない
会社を成長させ引退後は会長として居座れば 会社が面倒みてくれるかもしれない
畑を持てば農業ができる間は生きられる
あるいは今だとYoutuber等 自分の価値を上げておけば なんとかなる
Amazonの欲しいものリストとか

家賃経費をなくす

具体的にいえば家を買う事である
トータルで見れば家を買う方が家賃より安くなることも多いが
もし高くなるとしても、不安定な変数値を減らす事で
リスクが減る事が大きい

光熱費を下げる

大雑把にいえば、数人でシェアすると 光熱費は安くなる
基本料金が分割されたり、インターネットなんて確実にシェアしたい
ただし あまりにも大人数になると 電気などは使用量増えると高くなるので分岐点はある
もちろん 温泉施設等で 高圧電源が入っていたり、水利などがあると 計算が変わってくる
が 5人程度までなら 光熱費は絶対的に下がる

太陽光パネル等で前もって投資しておけば、トータルではどう転ぶかわからないが
ランニングコストのダウンにつながる可能性がある

水道やガス、インターネットを自分で作るのは難しそうだ。。。

ルームシェア

ルームシェア いわゆるシェアハウスにすれば
台所、ふろ、トイレのスペースがシェアされるため安くなるのはもちろん
光熱通信費もおさえられる
もちろん 無駄遣いしない人を選ぶ必要はある!
伴侶との比較は難しい
シェアメイトの方が人数メリット生かせるが法的な縛りの伴侶のメリットもある
が、基本的に私は普通の恋愛はないので、シェアメイトがいいと思う

食費を下げる

食費は厳密に計算する事はほぼ不可能である
許されるなら 畑や鶏、ヤギの飼育で食費を下げることも可能だが
住む場所にも左右されるし、労力も必要
だが 数年先には農業IoTでコストかからないと思ってる
しかし それより、田舎のじいちゃん ばあちゃんを助けるサービスを作り
野菜を送ってもらう方が現実的かもしれない
ので、じいちゃん ばあちゃんへの投資もあるかもしれない

魚は釣るより買う方が安いけど、養殖が出来れば 大きささえ確保すれば安くなるかもしれない
これは プロの施設が必要

健康

これが最も大切だ
健康が増えると寿命が延び、必須な金額が増えるかもしれないが、それは嬉しい副作用
健康であれば 病院のお金も減るし、QOLも向上するし、仕事もバイトも効率よくなる
一番重要なパラメータである!

が、私はあまり運動の趣味がない
球技とかやれば楽しいけどね
ってことで、しばらくお金を投資し、長続きする運動探しに投資する事にする

球技

基本的に球技はゲームなので、だいたい何をやっても楽しい
バレー、バスケ、テニス、フットサル、野球・・・・・
ただ球技は団体スポーツなので、周りとの関係が重要
幸い 今はネットで レベルに合ったチームを選んで楽しくプレイできるから 可能である
例えば中年テニスサークル等は お金持ちも多く、そこからビジネスにつながる可能性も無きにしも・・
ただし、生活のランニングコストは増える

ランニング、トレッキング、自転車

お金のかからないスポーツ ランニング
皇居マラソン等、仲間と走ったり 毎回いってれば仲間も出来るので
ランニングが楽しくなくても続けられる可能性がある
なにより 安くあげようと思えば これを超える安上がりはない
ラソン等の目標をかかげれば 意欲もわく

水泳、スケートなど

水泳は全身スポーツとして良い。区民プールなら安いし。

農業などの肉体労働

農業の手伝いとか参加してもいいかもしれない
運動不足解消で少ないがお駄賃もらえ
仲良くなれば野菜を送ってもらえるかもしれない
そもそも お金はいらないから 現物送ってもらいたい
かなり前向きに考えている

残り?

住むところ、食べ物、生活インフラ があれば、他はほとんど必要ない
趣味のゲームに関しては もともと大したお金かかってないし、下げれる要素も少ない
衣服やヘアカットは いくらでも下げれる
まだ他が思いつかない・・

まとめ

私の趣味は 生活のランニングコストを下げ、不確定要素を減らす事である
家賃収入を削るために家を買う。都内か田舎かわからないが。
数人でシェアする。人数が多いほど色々なリスクが削減できるので そのあたりは悩んでる
光熱費は太陽光パネル以外思いつかないし元はとれないかもしれないが、不確定要素減らすには効果あり
食費を減らすには 畑や家畜というのもあるが、住居次第なので、IoT農業とかに投資し 遠隔地で生産する方向がいい

健康のために運動をすることが最も重要なので、運動趣味に本格的に取り組みたい
まずは 農家の手伝いバイトをすることは重要
それ以外では 皇居ラン、トレッキング、水泳、球技・・・ 色々な運動を試して、長く続きそうなものを選ぶ
そのための投資は惜しまない

アーリーリタイアをして ゲームと OSS開発に貢献したい
また、今の自分の会社を存続させ、後継者にゆずり 自分は会長として君臨すれば 良さそう
その際に自社のプログラミング開発の手伝いをする
そのためには、後継者の育成(中)と 受け取ってもらえるような魅力のある組織作りが必要である
後継者もまだまだ若いので、譲れるのもあと5年ぐらい必要かもしれない(それでも若すぎる)
後継者以上の年齢の人が入っても 負けないような立場を与える必要がある
(後継者名義で 色々な講演させたり 名前を売る必要がある)
会社に関しては 色々な人と相談する必要がある
あと5年以内に方向性を決めたい

アーリーリタイア後の趣味は?

プログラムは趣味で書く。OSSに貢献する
あるいは自分の会社が残っていれば そこの開発に貢献する
ゲームが趣味なので 基本的にゲームで遊ぶ
美味しいもの、美味しいお茶が好き。ただし 喫煙も飲酒も出来ないので助かった。 その他の趣味も色々と細々とやる

Qiitaデイリーランキングにのった

qiita.com

過去に行った仕事のうち、自分的にヘビィだった案件を 大雑把に書いただけのポエムが
デイリーランキングきてしまった

守秘範囲内でしかかけないけど、案件ごとにもう少し詳細なことを書いていきたいな