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

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

ただいまの
回答率

90.34%

Unityでスプライトの重ね合わせで覆い焼きと乗算を適用したい

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,480

amery

score 127

タイトルの通りですが、
Photoshopで言うところのレイヤー構成が、
レイヤー1 ・・・ キャラクターの明るい部分(覆い焼きレイヤー)
レイヤー2 ・・・ キャラクターの暗い部分(乗算レイヤー)
レイヤー3 ・・・ キャラクターのベースになる部分(通常レイヤー)
という状態をUnityのスプライトを重ねて実現したいです。
スプライト1・・・覆い焼き用のスプライト
スプライト2・・・乗算用のスプライト
スプライト3・・・ベース用のスプライト (プレイヤーはここの色は自由に変えられる)

ビルトインシェーダーというものを使うとできるらしいと思い込み、
Unity公式から builtin_shaders-2017.1.3f1 をダウンロードしてきましたが、
どのファイルが覆い焼きなのか分からないのですが、そもそもこのやり方が合っているでしょうか?

◆環境
Unity2017 3.1f1

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

+2

ビルトインシェーダーの中の使えそうなファイルをコピーして、さらにそれを改造する必要があるのではないでしょうか?

「DefaultResourcesExtra/Sprites-Default.shader」をコピーして「Sprites-Multiply.shader」などと別名を付けて開いてみますと、先頭部分にShader "Sprites/Default"とシェーダー名を付けている部分がありますが、それをShader "Sprites/Multiply"とでも変えて新しい名前を付け、さらに真ん中あたりにBlend ...と書かれた行があるかと思いますので、ShaderLab: Blending - Unity マニュアルなどをご参考に変更してみてください。
新しいシェーダーをプロジェクトにインポートして、それを使ったマテリアルを作り、それをスプライトにセットすればカスタマイズされた独自の描画モードで合成されるはずです。

「乗算」はBlend DstColor Zero、「覆い焼き (リニア) - 加算」はBlend SrcAlpha Oneである程度再現できると思います。「覆い焼き (リニア) - 加算」を例示しますと、下記のようになるでしょう。

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Sprites/LinearDodge"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha One

        Pass
        {
        CGPROGRAM
            #pragma vertex SpriteVert
            #pragma fragment SpriteFrag
            #pragma target 2.0
            #pragma multi_compile_instancing
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
            #include "UnitySprites.cginc"
        ENDCG
        }
    }
}

ですが、「乗算」を同じようにやるとアルファチャンネルを持つスプライトの乗算が気に入らなかったり、あるいはリニアでない方の「覆い焼き」を再現したい...といったことがあるかもしれません。その場合はフラグメントシェーダーのカスタマイズも必要になるでしょう。

例えば「乗算」は、下記のようにするとPhotoshopの乗算に近づくと思います。

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Sprites/Multiply"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend DstColor Zero

        Pass
        {
        CGPROGRAM
            #pragma vertex SpriteVert
            #pragma fragment frag
            #pragma target 2.0
            #pragma multi_compile_instancing
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
            #include "UnitySprites.cginc"

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
                return fixed4((1.0 - c.a) + c.rgb * c.a, 1.0);
            }
        ENDCG
        }
    }
}

また、「覆い焼き」は多分下記のような感じでいかがでしょうか?こちらはバーテックスシェーダーにも手を加えて複雑になってしまい、グラブパスも使っているので実行コストも少し上がってしまいました。「覆い焼き (リニア) - 加算」で表現上問題なければ、そちらの方がおすすめです...

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Sprites/ColorDodge"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        GrabPass{}

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #pragma multi_compile_instancing
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
            #include "UnitySprites.cginc"

            struct v2fCustom
            {
                float4 vertex    : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_OUTPUT_STEREO
                float4 grabcoord : TEXCOORD1;
            };

            v2fCustom vert(appdata_t IN)
            {
                v2fCustom OUT;

                UNITY_SETUP_INSTANCE_ID (IN);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);

                OUT.vertex = UnityFlipSprite(IN.vertex, _Flip);
                OUT.vertex = UnityObjectToClipPos(OUT.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color * _RendererColor;

                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                OUT.grabcoord = ComputeGrabScreenPos(OUT.vertex);

                return OUT;
            }

            sampler2D _GrabTexture;

            fixed4 frag(v2fCustom IN) : SV_Target
            {
                fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
                fixed3 d = tex2Dproj(_GrabTexture, IN.grabcoord).rgb;
                return fixed4(d / (1.0 - c.rgb * c.a), c.a);
            }
        ENDCG
        }
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/12/12 07:51

    回答有り難うございます。どうもハードルが高そうですね・・・。試してみます。

    キャンセル

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

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

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