Help us understand the problem. What is going on with this article?

ShaderLab事始め

More than 5 years have passed since last update.

はじめに

UnityのShaderLabに関して、検証した内容を記述していきます。

使っているバージョンのシェーダーを入手する。

URLがちょくちょく変わるんですが、DownLoadページから使用しているUnityのバージョンに合わせた組み込みシェーダーのコードを取得します。
基本的にこれをベースに新しいシェーダーを作成するのがよいと思います。
2015/3/29時点のURL http://unity3d.com/jp/get-unity/download/archive

グレースケールを作る

入手したbuiltin-shadersを使って、スプライト用のグレースケールシェーダーを書いてみます。
シンプルにかけるので入門としては最適だとは思いますが、理論的な部分については下記の参考ページを確認してください。

サンプルコード

Monochrome.shader
Shader "Sprites/Monochrome"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

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

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ PIXELSNAP_ON
            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };

            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;
            const float3 _mono = float3(0.298912, 0.586611, 0.114478);

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
                c.rgb = dot(c.rgb, _mono) * c.a;
                return c;
            }
        ENDCG
        }
    }
}

元コードはDefaultResources/Sprite-Default.shaderです。
DefaultResourceExtra/Sprite-Default.shaderでもよいと思いますが、今回は検証してません。
追加・編集したのは

const float3 _mono = float3(0.298912, 0.586611, 0.114478);
c.rgb = dot(c.rgb, _mono) * c.a;

です。
ベクトルの各要素に係数をかけるような処理はいろいろありますが、組み込みAPIのdotを使うのが一番効率的です。
ベクトルの内積は次のように表せるので、各要素にウェイトをかけるような計算には重宝します。

dot([x,y,z],[a,b,c]) = x*a + y*b + z*c

Shaderの適用

GameObjectにShaderを適用するときには必ずMatrialを作成する必要があります。
Project上で右クリック-[Create]-[Material]で新規作成します。
Matrialを選択してInspectorからShaderを選び、Sprites/Monochromeを選択します。
これでモノクロマテリアルが完成したので、Hierarchy上のSpriteオブジェクトに対して適用してやります。

Shaderの変更

ShaderLabの変更は即時Unityエディタ上に反映されるようです。
先ほどのShaderが正しく実装されていれば、Gameはシーンビューですぐに確認できます。

参考ページ

公式サイトよりもわかりやすい解説をしたページがたくさんあります。
これらを見たあとで改めて公式サイトを読むと理解が深まると思います。
* http://d.hatena.ne.jp/nakamura001/20140421/1398083771#tb
* http://answers.unity3d.com/questions/343243/unlit-greyscale-shader.html
* http://wgld.org/d/webgl/w053.html

おまけ〜ネガシェーダー〜

上記はvertex shaderとfragment shaderで記述してみましたが、Unityではsurface shaderというライティング要素をUnityで計算したものを利用できるシェーダーを使う選択肢もあります。
というより、Unityの強力なライティング機能を利用したいなら基本的にこっちかなと言う気がします。
テストがてらsurface shaderを使って反転シェーダーを書いてみました。

Mobile/Nega.shader
Shader "Mobile/Nega" {
Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 150

CGPROGRAM
#pragma surface surf Lambert noforwardadd

sampler2D _MainTex;

struct Input {
    float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
    fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
    o.Albedo = 1.0f - c.rgb;
    o.Alpha = c.a;
}
ENDCG
}

Fallback "Mobile/VertexLit"
}

diffuseに相当する要素はAlbedoですが、まだちゃんと調べてないものもあるので要調査。
ネガがよくサンプルで使うんですが、イマイチ使い道ないんですよね・・・
ゲームで使用するとコントラストがけっこうきつい印象になるので、もう少し柔らかい色調に変換する必要があるかなと思います。

gree
インターネットを通じて、世界をより良くする。
http://gree.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした