質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.61%

shaderで処理したものにさらに処理する

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 2,229

shiroshiro_me

score 19

移動平均化フィルタの処理を繰り返すことで平滑化の度合いを上げるshaderプログラムを作りたいです。

https://qiita.com/yasuo_mc/items/67e5cf1d1f1c65535ae1

このサイトをもとに下に同じ処理を何度も書く方向で実装してみたのですが、
Shader error in 'RepeatAve2': Parse error: syntax error, unexpected TVAL_ID at line 99
というエラーが出て、実装できず困っています。TVAL_IDとはなんでしょうか。

また、最終的には3,4回ほど処理を繰り返してぼかしの様子を見てみたいと思っていますが、この方向性は現実的でしょうか。

Shader "Custom/RepeatAve2" {
    Properties
    {
        _Color("Color", Color) = (1, 1, 1, 1)

        _MainTex("Diffuse", 2D) = "white" {}
        _Noise("Noise", 2D) = "black" {}

        _Range("Range", Float) = 0.025
        _Blur("Blur", Float) = 0.005
        _Repeat("Repeat", int) = 1
        _Size("Size", int) = 3
    }

    SubShader
    {
        Cull Off

        GrabPass{ "_Frost" }

        CGINCLUDE
        #include "UnityCG.cginc"

        half4 _Color;

        sampler2D _MainTex;
        float4 _MainTex_ST;

        sampler2D _Frost;
        sampler2D _Noise;
        float4 _Noise_ST;

        half _Range;
        half _Blur;

        int _Size;
        int _Repeat;

        ENDCG

        Pass
        {
            CGPROGRAM
            #pragma target 3.0
            #pragma vertex vert
            #pragma fragment frag

            struct v2f
            {
                float4 pos : SV_POSITION;

                float3 uv : TEXCOORD;
                float4 screenPos : TEXCOORD1;
                float3 ray : TEXCOORD2;
            };

            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                o.screenPos = ComputeScreenPos(o.pos);
                o.ray = UnityObjectToViewPos(v.vertex).xyz * float3(-1, -1, 1);
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
                float2 uv = i.screenPos.xy / i.screenPos.w;

                float2 frostUV = tex2D(_Noise, i.uv * _Noise_ST.xy + _Noise_ST.zw).xy;

                frostUV -= 0.5;
                frostUV *= _Range;
                frostUV += uv;

                half4 frost = tex2D(_Frost, frostUV);
                for (int m = -(_Size - 1) / 2; m <= (_Size - 1) / 2; m++) {
                    for (int n = -(_Size - 1) / 2; n <= (_Size - 1) / 2; n++) {
                        frost += tex2D(_Frost, frostUV + float2(_Blur * m, _Blur * n));
                    }
                }

                frost /= _Size * _Size;

                half4 diffuse = tex2D(_MainTex, i.uv * _MainTex_ST.xy + _MainTex_ST.zw);

                half alpha = _Color.a * diffuse.a;

                return half4(frost.xyz + (diffuse.rgb * _Color.rgb * alpha), 1);
            }

            ENDCG
        }

            GrabPass{ "_Ave" }

            sampler2D _Ave;

                Pass
            {
                CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag

                struct v2f
            {
                float4 pos : SV_POSITION;

                float3 uv : TEXCOORD;
                float4 screenPos : TEXCOORD1;
                float3 ray : TEXCOORD2;
            };

            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                o.screenPos = ComputeScreenPos(o.pos);
                o.ray = UnityObjectToViewPos(v.vertex).xyz * float3(-1, -1, 1);
                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
            float2 uv = i.screenPos.xy / i.screenPos.w;

            float2 frostUV = tex2D(_Noise, i.uv * _Noise_ST.xy + _Noise_ST.zw).xy;

            frostUV -= 0.5;
            frostUV *= _Range;
            frostUV += uv;

            half4 frost = tex2D(_Ave, frostUV);
            for (int m = -(_Size - 1) / 2; m <= (_Size - 1) / 2; m++) {
                for (int n = -(_Size - 1) / 2; n <= (_Size - 1) / 2; n++) {
                    frost += tex2D(_Ave, frostUV + float2(_Blur * m, _Blur * n));
                }
            }

            frost /= _Size * _Size;

            half4 diffuse = tex2D(_MainTex, i.uv * _MainTex_ST.xy + _MainTex_ST.zw);

            half alpha = _Color.a * diffuse.a;

            return half4(frost.xyz + (diffuse.rgb * _Color.rgb * alpha), 1);
            }

                ENDCG
            }
    }
        Fallback Off
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

変数_Aveの宣言がCGPROGRAMENDCGの間に入っていないことによるエラーと思われます。
下記のような書き換えではどうでしょうか?

// 省略

            GrabPass{ "_Ave" }

            // sampler2D _Ave; // これを...

                Pass
            {
                CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
                sampler2D _Ave; // ここに引っ越し
                struct v2f
            {
                float4 pos : SV_POSITION;

                float3 uv : TEXCOORD;
                float4 screenPos : TEXCOORD1;
                float3 ray : TEXCOORD2;
            };

// 省略

繰り返しについては、確かにGrabPassを過剰に使うのは高コストでしょうが、3~4回程度なら十分現実的だろうと思います。実際にやってパフォーマンスを見てみて、回数を検討するのがいいでしょうね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る