数式をグラフ化する。Grapher(macアプリ) と desmos(webサービス)

最近知りましたが、macには標準でグラフを描くアプリが入っていました。 これでガウス関数を作ってみます。

mac標準アプリのGrapher

パラメータ化した値を操作して動かす事も出来る。 f:id:ssr_maguro:20191121121102g:plain

どんなパラメーターになるのか理解するのに役立ちそう。

しかし

ちょっとしか触っていませんが、どうも挙動がバグっぽいものが目立ちました。 入力欄の色が変わってしまったり、アニメーションさせるとグラフが突然ずれたり。

真打ち、desmos

webサービスでも同じような事が出来るサービスがあるんですね。 作ったものを共有できるし、使いやすい。目立ったバグもなさそう。 入力方法もGrapherと同じ感覚で出来ました。

右下の「desmos」というロゴをクリックするとサイトに飛びます。 www.desmos.com

サイトに飛ぶとパラメータを操作してグラフがどんな風に変化するのかが視覚的に理解できます。 これは便利だ。というか、理解するためには必須級だと思いました。 数式見ただけでは何も分からない。。

こちらの記事にて知りました。ありがとうございます。

【Unityシェーダ入門】スパイクノイズを作る - おもちゃラボ

Unityでガウシアンブラーを実装する - e.blog

PostProcessing Stackのカスタムエフェクトで解像度を下げる (ダウンサンプリングする) 方法

f:id:ssr_maguro:20191120174741g:plain

参考にしたソース https://github.com/Unity-Technologies/PostProcessing/blob/v2/PostProcessing/Runtime/Effects/ScalableAO.cs

    // AO buffer
    var rtMask = ShaderIDs.OcclusionTexture1;
    int scaledWidth = context.width / ts;
    int scaledHeight = context.height / ts;
    context.GetScreenSpaceTemporaryRT(cmd, rtMask, 0, kFormat, kRWMode, kFilter, scaledWidth, scaledHeight);

ここらへん。

context.GetScreenSpaceTemporaryRT() などを使って、CommandBufferの操作が出来る。

解像度を下げるだけならshaderは不要で、下記で出来た。

    using System;
    using UnityEngine;
    using UnityEngine.Rendering.PostProcessing;
    
    namespace White
    {
        [Serializable]
        [PostProcess(typeof(DownSamplingRenderer), PostProcessEvent.AfterStack,
            "AAA/PostEffects/DownSamplilng", true)]
        public sealed class DownSampling : PostProcessEffectSettings
        {
            [Range(1f, 10f)] public FloatParameter downScale = new FloatParameter {value = 1f};
        }
    
        internal sealed class DownSamplingRenderer : PostProcessEffectRenderer<DownSampling>
        {
            public override void Render(PostProcessRenderContext context)
            {
                int scaledWidth = Mathf.RoundToInt(context.width / settings.downScale.value);
                int scaledHeight = Mathf.RoundToInt(context.height / settings.downScale.value);
    
                int tempId1 = Shader.PropertyToID("_Temp1");
                context.GetScreenSpaceTemporaryRT(context.command, tempId1, 0, RenderTextureFormat.ARGB32,
                    RenderTextureReadWrite.Linear, FilterMode.Bilinear,
                    scaledWidth, scaledHeight);
    
                // 元画像をtempId1にコピー
                context.command.BuiltinBlit(context.source, tempId1);
                // tempId1を出力
                context.command.BuiltinBlit(tempId1, context.destination);
                context.command.ReleaseTemporaryRT(tempId1);
            }
        }
    }

CommandBufferと同じ。

GetScreenSpaceTemporaryRT() contextのものを使うのは何でか?

context.command.GetTemporaryRT() に置き換えて試したが、これでも同じ結果が得られる。

context.command.GetTemporaryRT(tempId1, scaledWidth, scaledHeight, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);

GetScreenSpaceTemporaryRT()のソースを見ると、 #if UNITY_2017_2_OR_NEWER で処理を分岐させている。

BuiltinBlit()に関してもCommandBufferに実装された関数ではなく、PostProcessing.RuntimeUtilitiesで宣言されている拡張メソッド。

将来的に何かの処理が挟まる可能性もあるのでCommandBufferのメソッドをそのまま使うのは止めたほうが良さそうだ。

GetScreenSpaceTemporaryRT 等の詳しいapi documentはこちら。https://docs.unity3d.com/Packages/com.unity.postprocessing@2.2/api/UnityEngine.Rendering.PostProcessing.RuntimeUtilities.html?q=BlitFullscreenTriangle#UnityEngine_Rendering_PostProcessing_RuntimeUtilities_CopyTexture_CommandBuffer_RenderTargetIdentifier_RenderTargetIdentifier_

PostProcessing Stack v2でカスタムエフェクトを作る

公式マニュアルはhttps://docs.unity3d.com/Packages/com.unity.postprocessing@2.2/manual/Writing-Custom-Effects.html

公式 APIドキュメント https://docs.unity3d.com/Packages/com.unity.postprocessing@2.2/api/

どちらもバージョンに注意。 使い方は公式マニュアルで全て説明されている。 ここでは、マニュアルを読んだ上で個人的なメモを纏めていく。

ハマりポイント

一番重要そうで忘れがちな部分を先に書く。 shaderがC#ファイルからしか参照されていないと、shaderがビルドに含まれない。 PostProcessingStack用のカスタムエフェクトを作ると、大抵こうなるはず。

Resourcesフォルダーに追加するか、Always Included Shaders(Edit -> Project Settings -> Graphics)に追加する必要がある。

さすがにこれは将来的なバージョンUPで対応されるのでは?

ファイル構成

  • c# + shaderのセット
  • shaderはshaderLabではなく、HLSL
  • 公式マニュアルにはHLSLと書いてあるが、ShaderLabでも動作する

属性部分について

[Serializable]
[PostProcess(typeof(RadialBlurRenderer), PostProcessEvent.AfterStack, "AAA/PostEffects/Radial Blur HLSL", true)]

エフェクトの注入ポイント

  • BeforeTransparent:透明なパスが完了する前に、効果は不透明なオブジェクトにのみ適用されます。
  • BeforeStack:組み込みスタックが起動する前にエフェクトが適用されます。これには、アンチエイリアス被写界深度、トーンマッピングなどが含まれます。
  • AfterStack:エフェクトは、ビルトインスタックの後、FXAA(有効な場合)および最終パスディザリングの前に適用されます。

メニューカテゴリ パスはココに表示されるための記述。

SceneViewでも有効にするか

最後に、オプションの4番目のパラメーターがallowInSceneViewあり、その名前が示すように、シーンビューでエフェクトを有効にするかどうかを指定します。trueデフォルトではに設定されていますが、一時的な効果やレベルの編集を難しくする効果のために無効にすることができます。

便利なことに、最初からScene ViewでもPostEffectがpreviewできる仕組みが整っている。 しかし逆にそれが邪魔になる事があるので、Offにする事も可能。

レンダラー部分

ドキュメントのサンプル

public sealed class GrayscaleRenderer : PostProcessEffectRenderer<Grayscale>
{
    public override void Render(PostProcessRenderContext context)
    {
        var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/Grayscale"));
        sheet.properties.SetFloat("_Blend", settings.blend);
        context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
    }
}

PostProcessRenderContext型の引数が渡されるので、そこから情報を得る。

https://github.com/Unity-Technologies/PostProcessing/blob/v2/PostProcessing/Runtime/PostProcessRenderContext.cs

PostProcessEffectRendererを継承する。

https://github.com/Unity-Technologies/PostProcessing/blob/v2/PostProcessing/Runtime/PostProcessEffectRenderer.cs

PostProcessEffectRendererでoverrideして使える関数

  • void Init():レンダラーの作成時に呼び出されます。
  • DepthTextureMode GetLegacyCameraFlags():カメラフラグを設定し、深度マップ、モーションベクトルなどを要求するために使用されます。
  • void ResetHistory():「履歴のリセット」イベントが送出されたときに呼び出されます。主に一時的な効果に使用され、履歴バッファなどをクリアします。
  • void Release():レンダラーが破棄されるときに呼び出されます。必要に応じてクリーンアップを行ってください。

パラメーターが変更された時のイベントが欲しかったが、今の所無かった。自力でチェックする必要がある。

shader

shaderLabではなく、HLSLで書く必要がある。

ドキュメントのサンプル

Shader "Hidden/Custom/Grayscale"
{
    HLSLINCLUDE

        #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"

        TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
        float _Blend;

        float4 Frag(VaryingsDefault i) : SV_Target
        {
            float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
            float luminance = dot(color.rgb, float3(0.2126729, 0.7151522, 0.0721750));
            color.rgb = lerp(color.rgb, luminance.xxx, _Blend.xxx);
            return color;
        }

    ENDHLSL

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            HLSLPROGRAM

                #pragma vertex VertDefault
                #pragma fragment Frag

            ENDHLSL
        }
    }
}

#include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"

は必ず必要。ここのパスはバージョンによって違うようなので注意。

https://github.com/Unity-Technologies/PostProcessing/blob/v2/PostProcessing/Shaders/StdLib.hlsl

https://github.com/Unity-Technologies/PostProcessing/tree/v2/PostProcessing/Shaders/API

テクスチャ宣言

TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);


PostProcessing/PostProcessing/Shaders/API/

どんなマクロがあるのかは、ここのファイルをチェックするのが良いとの事。

Metal用はこちら。

https://github.com/Unity-Technologies/PostProcessing/blob/v2/PostProcessing/Shaders/API/Metal.hlsl

カスタムエディター

自作で拡張も可能。その仕組も用意されている。

unity C#でのpath取得関連メモ

project viewで選択中のディレクトリ取得

    static private string GetSelectedDir()
    {
        foreach (Object obj in Selection.GetFiltered(typeof(DefaultAsset), SelectionMode.TopLevel))
        {
            if (obj is DefaultAsset)
            {
                string path = AssetDatabase.GetAssetPath(obj);

                if (AssetDatabase.IsValidFolder(path))
                {
                    return path;
                }
            }
        }

        return "";
    }

カレントディレクトリの取得。unity editorで実行すると、Projectが入ってるディレクトリの絶対パスが入っているようだ。

System.Environment.CurrentDirectory
var a = GetSelectedDir(); // Assets/xxx/xxx みたいな Assetsからの相対パス

var b = System.IO.Path.GetFullPath(a); // 絶対パス変換

 

ディレクトリを再帰的にコピー

https://docs.microsoft.com/ja-jp/dotnet/standard/io/how-to-copy-directories

 

Unity2019.1 LWRPでのRenderScale、Renderer Featuresの並べ替え

パッケージマネージャーのLightwight RPは5.13.0を使用。

f:id:ssr_maguro:20190510151035p:plain f:id:ssr_maguro:20190510152727p:plain

    public ScriptableRendererData _data;
    public LightweightRenderPipelineAsset _asset;

をinspecterで設定した後、動的に変更する。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Rendering.LWRP;

public class LWRPTest : MonoBehaviour
{
    public ScriptableRendererData data;
    public LightweightRenderPipelineAsset asset;

    public Button btn1;
    public Button btn2;

    // Start is called before the first frame update
    void Start()
    {
        List<ScriptableRendererFeature> copy = new List<ScriptableRendererFeature>();
        foreach (ScriptableRendererFeature f in data.rendererFeatures)
        {
            copy.Add(f);
        }

        btn1.onClick.AddListener(() =>
        {
            // Renderer Features並べ替え
            data.rendererFeatures[0] = copy[1];
            data.rendererFeatures[1] = copy[0];
        });

        btn2.onClick.AddListener(() =>
        {
            // RenderScale
            asset.renderScale = 0.5f;
        });
    }
}

参考

Lightwight RPのバージョンが低いとScriptableRendererFeatureを設定できないので注意。

tsubakit1.hateblo.jp