自己皇帝感

をください

心のよりどころなくなった

自作えっちゲームの宣伝のfavが1000を超えた。
学生のころからえっちゲーム制作をしてみたいと思っていて、まずは1000本売り上げようとおもい、既存の作品でそのラインにのっているのはfavが1000以上あるものだったので、まずはそれを目標にしていた。
いつかそっちで飯がくえたらいいなあと漠然と考えつつ大学とか仕事とか人生を過ごしていた。


自分は思った以上にメンタルが弱く結構気持ちが苦しくなることがある。
仕事は周りの方が全然優秀だし、人生設計もしっかりしているし、自立している。
自分は(すごい怠けていたというわけではないが)今の自分ができる範囲で頑張ろう、それでだめならしょうがない、
「まぁ今の手札が全部だめになったら、ゲーム制作する時間がとれるしいっか」と考えることで、苦しみを和らげていた。
急場な時は多少抗不安薬が必要なぐらいメンタルがつらい時もあったが、それでもこの券のことを考えていれば最悪ではなかった。
自分にとってゲーム制作は手札とは関係ない「次の試合への参加券」だった。これを持っている限り、自分の心は安泰だった。


そういう考えで過ごし始めてから10年、ゲーム制作という夢の、最初の目標が今日達成された。
めちゃくちゃ嬉しい。だけどその瞬間から動機が止まらない。今までにない恐怖が襲ってきた。
自分の書いた糞な卒論を発表しないといけなかった日を同じぐらい苦しい。でも原因がわからない。
30分寝ても解決しない。友人に褒めてもらっても(嬉しいけど)心が休まらない。気をそらしたくて何時間もyoutubetwitterを見てしまった。
かえって体がどんどん重くなって、動けなくなりそうだった。


ネットの情報を遮断するため銭湯にいって、頭を整理することにした。


現実の恐怖が苦しいとき、ゲーム制作のことについて考えると和らげることができた。でも今日、夢の最初の目標を達成したことで、労力とリターンの計算が現実味を帯びてきて、その輪郭がはっきりしてきた。
そうして「次の試合への参加券」は、今持っている手札と同じ形であることに気づいてしまった。


言語化できたことで幾分は楽になった。それでもこれからの絶望は計り知れない。
自分は今から、10年間なぁなぁで切ってきたこの手札に、真正面から向き合わなければならない。その恐怖に耐えきれるだろうか。






もう一つの券も学生のころから持っている。使いたくなくて見ないようにしていたけど、今後恐怖に負けた時はこれに頼らざるをえないかもしれない。
北欧に健康な人間でも安楽死させてくれる組織があるらしい」。

UnityVFXで極座標ノイズをつくる

youtu.be
ノイズテクスチャに極座標ノードを付けて同心円状のノイズを作っているのを見た。
VFXの勉強がてらこれをやってみた

動画ではノイズテクスチャをつっていたが、面倒だったのでノイズノードを使おうとした。
テクスチャの代わりにノイズノードにつけたが、画面下半分に縦線が入る

縦線の右側がuv.y=0.5、左側がuv.y=-0.5になっている

この縦線をまたいでもきれいにつながってほしい。
つまりノイズの方を常に「noise(y)=noise(y+1)」というなるようなものを作れば、極座標ノードにつけてもきれいに渦巻っぽいノイズになるはず

単に「周期1で繰り返す」ノイズではだめで、切れ目ができてしまう

そこで周期2のノイズを用意(noise_2と呼ぶ、y=2->0の時に切れ目がある)し、

output = lerp ( (noise_2(y+1) , noise_2(y), t) (ただし t=abs(-mod(y,2)+1))

y=0のとき、t=1, noise_2(y+1) = noise_2(1) の比重がおおきいので切れ目がない
y=1のとき、t=0, noise_2(y) = noise_2(1) の比重がおおきいので切れ目がない
y=2のとき、t=1, noise_2(y+1) = noise_2(1) の比重がおおきいので切れ目がない
という風に、切れ目のないほうの比重が大きくなるようにできる

modの部分はmoduloにしたかったが、負の数をいい感じにしてくれないので代わりにperiodicていうサブグラフ作った


こうして、「y方向に周期1できれいにつながるノイズ」がでいたので、YLoopNoiseと名付けて、極座標ノードにつけてみた

予想どおりノイズ下半分の縦線がなくなった

Unity 2Dレンダラで3Dオブジェクトをライティングする

qiita.com
ノーマルマップがないモデルだといい感じにライティングされなかったからこれ多分モデルにノーマルマップがあるときの事例だと思う(未検証)

頂点のノーマルだけで事足りる場合もあるのでちょっと改変した

〜
shader "Universal Render Pipeline/2D/Sprite-Lit-3D"
{
    Properties
    {
        [MainTexture] _MainTex("Diffuse", 2D) = "white" {}
        [MainColor] _BaseColor("Color", Color) = (1,1,1,1)
        [HDR] _EmissionColor("Emission", Color) = (0,0,0,0)
        _MaskTex("Mask", 2D) = "white" {}
        _NormalMap("Normal Map", 2D) = "bump" {}

        // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
        [HideInInspector] _Color("Tint", Color) = (1,1,1,1)
        [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
        [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
        [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
    }

    HLSLINCLUDE
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    ENDHLSL

    SubShader
    {
        Tags {"Queue" = "Geometry" "RenderType" = "Opacue" "RenderPipeline" = "UniversalPipeline" }

        Blend SrcAlpha OneMinusSrcAlpha
        Cull Back
        ZWrite On

        Pass
        {
            Tags { "LightMode" = "Universal2D" }
            HLSLPROGRAM
            #pragma prefer_hlslcc gles
            #pragma vertex CombinedShapeLightVertex
            #pragma fragment CombinedShapeLightFragment
            #pragma multi_compile USE_SHAPE_LIGHT_TYPE_0 __
            #pragma multi_compile USE_SHAPE_LIGHT_TYPE_1 __
            #pragma multi_compile USE_SHAPE_LIGHT_TYPE_2 __
            #pragma multi_compile USE_SHAPE_LIGHT_TYPE_3 __

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float4 color        : COLOR;
                float2  uv           : TEXCOORD0;
            };

            struct Varyings
            {
                float4  positionCS  : SV_POSITION;
                float4  color       : COLOR;
                float2  uv          : TEXCOORD0;
                float2  lightingUV  : TEXCOORD1;
            };

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/LightingUtility.hlsl"

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            TEXTURE2D(_MaskTex);
            SAMPLER(sampler_MaskTex);
            TEXTURE2D(_NormalMap);
            SAMPLER(sampler_NormalMap);
            half4 _MainTex_ST;
            half4 _NormalMap_ST;
            half4 _BaseColor;
            half4 _EmissionColor;

            #if USE_SHAPE_LIGHT_TYPE_0
            SHAPE_LIGHT(0)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_1
            SHAPE_LIGHT(1)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_2
            SHAPE_LIGHT(2)
            #endif

            #if USE_SHAPE_LIGHT_TYPE_3
            SHAPE_LIGHT(3)
            #endif

            Varyings CombinedShapeLightVertex(Attributes v)
            {
                Varyings o = (Varyings)0;

                o.positionCS = TransformObjectToHClip(v.positionOS);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                float4 clipVertex = o.positionCS / o.positionCS.w;
                o.lightingUV = ComputeScreenPos(clipVertex).xy;
                o.color = v.color * _BaseColor;
                return o;
            }

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/CombinedShapeLightShared.hlsl"

            half4 CombinedShapeLightFragment(Varyings i) : SV_Target
            {
                half4 main = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                half4 mask = SAMPLE_TEXTURE2D(_MaskTex, sampler_MaskTex, i.uv);

                return CombinedShapeLightShared(main, mask, i.lightingUV)+main*_EmissionColor;
            }
            ENDHLSL
        }

        Pass
        {
            Tags { "LightMode" = "NormalsRendering"}
            HLSLPROGRAM
            #pragma prefer_hlslcc gles
            #pragma vertex NormalsRenderingVertex
            #pragma fragment NormalsRenderingFragment

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float3 normalOS     : NORMAL;//ここで頂点の法線を取得
                float4 color        : COLOR;
                float2 uv           : TEXCOORD0;
                float4 tangent      : TANGENT;
            };

            struct Varyings
            {
                float4  positionCS      : SV_POSITION;
                float4  color           : COLOR;
                float2  uv              : TEXCOORD0;
                float3  normalWS        : TEXCOORD1;
                float3  tangentWS       : TEXCOORD2;
                float3  bitangentWS     : TEXCOORD3;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            TEXTURE2D(_NormalMap);
            SAMPLER(sampler_NormalMap);
            float4 _NormalMap_ST;  // Is this the right way to do this?

            Varyings NormalsRenderingVertex(Attributes attributes)
            {
                Varyings o = (Varyings)0;

                o.positionCS = TransformObjectToHClip(attributes.positionOS);
                o.uv = TRANSFORM_TEX(attributes.uv, _NormalMap);
                o.uv = attributes.uv;
                o.color = attributes.color;
                o.normalWS = TransformObjectToWorldDir(attributes.normalOS);
                o.tangentWS = TransformObjectToWorldDir(attributes.tangent.xyz);
                o.bitangentWS = cross(o.normalWS, o.tangentWS) * attributes.tangent.w;
                return o;
            }

            #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"

            float4 NormalsRenderingFragment(Varyings i) : SV_Target
            {
                float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                float3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, i.uv));
                //return NormalsRenderingShared(mainTex, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);
                half3 normalVS = TransformWorldToViewDir(i.normalWS.xyz);//頂点の法線情報をそのまま使う
                half4 normalColor;
                    
                normalColor.rgb = 0.5 * ((normalVS)+1);
                normalColor.a = i.color.a;  // used for blending

                return normalColor;
            }
            ENDHLSL
        }
        Pass
        {
            Tags { "LightMode" = "UniversalForward" "Queue"="Geometry" "RenderType"="Opacue"}

            HLSLPROGRAM
            #pragma prefer_hlslcc gles
            #pragma vertex UnlitVertex
            #pragma fragment UnlitFragment

            struct Attributes
            {
                float3 positionOS   : POSITION;
                float4 color        : COLOR;
                float2 uv           : TEXCOORD0;
            };

            struct Varyings
            {
                float4  positionCS      : SV_POSITION;
                float4  color           : COLOR;
                float2  uv              : TEXCOORD0;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            float4 _MainTex_ST;

            Varyings UnlitVertex(Attributes attributes)
            {
                Varyings o = (Varyings)0;

                o.positionCS = TransformObjectToHClip(attributes.positionOS);
                o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
                o.uv = attributes.uv;
                o.color = attributes.color;
                return o;
            }

            float4 UnlitFragment(Varyings i) : SV_Target
            {
                float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                return mainTex;
            }
            ENDHLSL
        }
    }

    FallBack "Universal Render Pipeline/Unlit"
}
〜

Tags { "LightMode" = "NormalsRendering"}
のPassで
頂点シェーダで法線情報をもらって
NormalsRenderingFragmentでそのままつかっただけ

f:id:stalagmite:20210829170155p:plain

白いCubeは3dモデルだけど松明のLight2D(PointLight)の光を受けている

uraymarchingメモ

コード例

#ifndef VERT_FRAG_DEFERRED_OBJECT_STANDARD_H
#define VERT_FRAG_DEFERRED_OBJECT_STANDARD_H

#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "UnityPBSLighting.cginc"

#include "./Structs.cginc"
#include "./Raymarching.cginc"
#include "./Utils.cginc"

int _Loop;
float _MinDistance;
fixed4 _Color;
float _Glossiness;
float _Metallic;

#ifdef FULL_SCREEN

struct v2f
{
    float4 pos         : SV_POSITION;
    float4 projPos     : TEXCOORD0;
    float4 lmap        : TEXCOORD1;
#ifdef LIGHTMAP_OFF
    #if UNITY_SHOULD_SAMPLE_SH
    half3 sh           : TEXCOORD2;
    #endif
#endif
};

#else

struct v2f
{
    float4 pos         : SV_POSITION;
    float3 worldPos    : TEXCOORD0;
    float3 worldNormal : TEXCOORD1;
    float4 projPos     : TEXCOORD2;
    float4 lmap        : TEXCOORD3;
#ifdef LIGHTMAP_OFF
    #if UNITY_SHOULD_SAMPLE_SH
    half3 sh           : TEXCOORD4;
    #endif
#endif
};

#endif

v2f Vert(appdata_full v)
{
    v2f o;

#ifdef FULL_SCREEN
    o.pos = v.vertex;
#else
    o.pos = UnityObjectToClipPos(v.vertex);
    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    o.worldNormal = UnityObjectToWorldNormal(v.normal);
#endif
    o.projPos = ComputeNonStereoScreenPos(o.pos);
    COMPUTE_EYEDEPTH(o.projPos.z);

#ifndef DYNAMICLIGHTMAP_OFF
    o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#else
    o.lmap.zw = 0;
#endif

#ifndef LIGHTMAP_OFF
    o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#else
    o.lmap.xy = 0;
    #ifndef SPHERICAL_HARMONICS_PER_PIXEL
        #if UNITY_SHOULD_SAMPLE_SH
    o.sh = 0;
    o.sh = ShadeSHPerVertex(o.worldNormal, o.sh);
        #endif
    #endif
#endif

    return o;
}

GBufferOut Frag(v2f i, GBufferOut o)
{
    RaymarchInfo ray;
    INITIALIZE_RAYMARCH_INFO(ray, i, _Loop, _MinDistance);
    Raymarch(ray);

#ifdef USE_RAYMARCHING_DEPTH
    o.depth = ray.depth;
#endif

    float3 worldPos = ray.endPos;
    float3 worldNormal = 2.0 * ray.normal - 1.0;
    fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

    SurfaceOutputStandard so;
    UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard, so);
    so.Albedo = _Color.rgb;
    so.Metallic = _Metallic;
    so.Smoothness = _Glossiness;
    so.Emission = 0.0;
    so.Alpha = _Color.a;
    so.Occlusion = 1.0;
    so.Normal = worldNormal;

#ifdef POST_EFFECT
    POST_EFFECT(ray, so);
#endif

    UnityGI gi;
    UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    gi.indirect.diffuse = 0;
    gi.indirect.specular = 0;
    gi.light.color = 0;
    gi.light.dir = half3(0, 1, 0);
    gi.light.ndotl = LambertTerm(worldNormal, gi.light.dir);

    UnityGIInput giInput;
    UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
    giInput.light = gi.light;
    giInput.worldPos = worldPos;
    giInput.worldViewDir = worldViewDir;
    giInput.atten = 1;

#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
    giInput.lightmapUV = i.lmap;
#else
    giInput.lightmapUV = 0.0;
#endif

#if UNITY_SHOULD_SAMPLE_SH
    #ifdef SPHERICAL_HARMONICS_PER_PIXEL
    giInput.ambient = ShadeSHPerPixel(worldNormal, 0.0, worldPos);
    #else
    giInput.ambient.rgb = i.sh;
    #endif
#else
    giInput.ambient.rgb = 0.0;
#endif

    giInput.probeHDR[0] = unity_SpecCube0_HDR;
    giInput.probeHDR[1] = unity_SpecCube1_HDR;

#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
    giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
#endif

#if UNITY_SPECCUBE_BOX_PROJECTION
    giInput.boxMax[0] = unity_SpecCube0_BoxMax;
    giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
    giInput.boxMax[1] = unity_SpecCube1_BoxMax;
    giInput.boxMin[1] = unity_SpecCube1_BoxMin;
    giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
#endif

    LightingStandard_GI(so, giInput, gi);

    o.emission = LightingStandard_Deferred(so, worldViewDir, gi, o.diffuse, o.specular, o.normal);
#ifndef UNITY_HDR_ON
    o.emission.rgb = exp2(-o.emission.rgb);
#endif

    UNITY_OPAQUE_ALPHA(o.diffuse.a);

    return o;
}

#endif
Shader "Raymarching/Forward_HexFloor"
{

Properties
{
    [Header(PBS)]
    _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
    _Metallic("Metallic", Range(0.0, 1.0)) = 0.5
    _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5

    [Header(Pass)]
    [Enum(UnityEngine.Rendering.CullMode)] _Cull("Culling", Int) = 2

    [Header(Raymarching)]
    _Loop("Loop", Range(1, 100)) = 30
    _MinDistance("Minimum Distance", Range(0.001, 0.1)) = 0.01
    _DistanceMultiplier("Distance Multiplier", Range(0.001, 2.0)) = 1.0

    [PowerSlider(10.0)] _NormalDelta("NormalDelta", Range(0.00001, 0.1)) = 0.0001

// @block Properties
[Header(Additional Properties)]
_TopColor("TopColor", Color) = (1, 1, 1, 0)
// @endblock
}

SubShader
{

Tags
{
    "RenderType" = "Opaque"
    "Queue" = "Geometry"
    "DisableBatching" = "True"
}

Cull [_Cull]

CGINCLUDE

#define OBJECT_SHAPE_CUBE

#define USE_RAYMARCHING_DEPTH

#define SPHERICAL_HARMONICS_PER_PIXEL

#define DISTANCE_FUNCTION DistanceFunction
#define POST_EFFECT PostEffect
#define PostEffectOutput SurfaceOutputStandard

#include "Assets\uRaymarching\Shaders\Include\Legacy/Common.cginc"

// @block DistanceFunction
inline float DistanceFunction(float3 pos)
{
    // combine even hex tiles and odd hex tiles

    float radius = 0.2;
    float space = 0.1;
   float wave = 0.1;
    float3 objectScale = GetScale();
    float height = objectScale.y * 0.5 - wave;
    float3 scale = objectScale * 0.5;

    float pitch = radius * 2 + space;
    float3 offset = float3(pitch * 0.5, 0.0, pitch * 0.866);
    float3 loop = float3(offset.x * 2, 1.0, offset.z * 2);
    
   float3 p1 = pos;
    float3 p2 = pos + offset;

    // calculate indices
   float2 pi1 = floor(p1 / loop).xz;
    float2 pi2 = floor(p2 / loop).xz;
   pi1.y = pi1.y * 2 + 1;
    pi2.y = pi2.y * 2;

    p1 = Repeat(p1, loop);
   p2 = Repeat(p2, loop);

    // draw hexagonal prisms with random heights
   float dy1 = wave * sin(10 * Rand(pi1) + 5 * PI * _Time.x);
    float dy2 = wave * sin(10 * Rand(pi2) + 5 * PI * _Time.x);
    float d1 = HexagonalPrismY(float3(p1.x, pos.y + dy1, p1.z), float2(radius, height));
    float d2 = HexagonalPrismY(float3(p2.x, pos.y + dy2, p2.z), float2(radius, height));

    // maximum indices
    loop.z *= 0.5;
    float2 mpi1 = floor((scale.xz + float2(space * 0.5,    radius)) / loop.xz);
    float2 mpi2 = floor((scale.xz + float2(radius + space, radius)) / loop.xz);

    // remove partial hexagonal prisms
    // if (pi1.x >= mpi1.x || pi1.x <  -mpi1.x) d1 = max(d1, space);
    // if (pi1.y >= mpi1.y || pi1.y <= -mpi1.y) d1 = max(d1, space);
    float o1 = any(
        step(mpi1.x, pi1.x) +
        step(pi1.x + 1, -mpi1.x) +
        step(mpi1.y, abs(pi1.y)));
   d1 = o1 * max(d1, 0.1) + (1 - o1) * d1;

    //  if (!all(max(mpi2 - abs(pi2), 0.0))) d2 = max(d2, space);
    float o2 = any(step(mpi2, abs(pi2)));
    d2 = o2 * max(d2, 0.1) + (1 - o2) * d2;

    // combine
    //return min(d1, d2);
return d1;
}
// @endblock

// @block PostEffect
float4 _TopColor;

inline void PostEffect(RaymarchInfo ray, inout PostEffectOutput o)
{
    float3 localPos = ToLocal(ray.endPos);
    o.Emission += smoothstep(0.48, 0.50, localPos.y) * _TopColor;
    o.Occlusion *= 1.0 - 1.0 * ray.loop / ray.maxLoop;
}
// @endblock

ENDCG

Pass
{
    Tags { "LightMode" = "Deferred" }

    Stencil
    {
        Comp Always
        Pass Replace
        Ref 128
    }

    CGPROGRAM
    #include "Assets\uRaymarching\Shaders\Include\Legacy/DeferredStandard.cginc"
    #pragma target 3.0
    #pragma vertex Vert
    #pragma fragment Frag
    #pragma exclude_renderers nomrt
    #pragma multi_compile_prepassfinal
    #pragma multi_compile ___ UNITY_HDR_ON
    ENDCG
}

}

Fallback "Raymarching/Fallbacks/StandardSurfaceShader"

CustomEditor "uShaderTemplate.MaterialEditor"

}

仕組み

  • vertexシェーダでprojPosにComputeNonStereoScreenPosでスクリーン上の座標を入れとくことで後のポストエフェクトに使いやすくしている(利便性のためzはEYE_DEPTHを適用してビュー空間上の深度に変換している。)
  • PostEffect関数で返すべきデータの種類がレンダリングモードに応じて適切に選択できるように、PostEffectOutputをdefineしている(どう変わるかはhttps://github.com/hecomi/uRaymarching/blob/master/Documents/Legacy.md のPostEffectを参照)

unity shader

  1. [Unity] 邪道なDeferredの使い方で苦しんだ話(昼夜のドット絵で夕焼けアニメ:2) - Qiita
  2. https://qiita.com/Shinoda_Naoki/items/31bde73218b0295b8778

Unity でオブジェクトスペースの Raymarching をフォワードレンダリングでやってみた - 凹みTips

アニメCG