スクリーンショット_2019-08-21_22

8/24までの進捗

unityのshaderで星空風の絵を描いてみた。

たまにはコードを晒して自分の理解を整理してみる。

    Shader "Unlit/UnlitStarryShader"
   {
       Properties
       {
           _MainTex ("Texture", 2D) = "white" {}
       }
       SubShader
       {
           Tags { "RenderType"="Opaque" }
           LOD 100

           Pass
           {
               CGPROGRAM
               #pragma vertex vert
               #pragma fragment frag
               // make fog work
               #pragma multi_compile_fog

               #include "UnityCG.cginc"

               struct appdata
               {
                   float4 vertex : POSITION;
                   float2 uv : TEXCOORD0;
               };

               struct v2f
               {
                   float2 uv : TEXCOORD0;
                   UNITY_FOG_COORDS(1)
                   float4 vertex : SV_POSITION;
               };

               sampler2D _MainTex;
               float4 _MainTex_ST;

               v2f vert (appdata v)
               {
                   v2f o;
                   //座標変換。空間座標からカメラ座標への変換を行っている
                   o.vertex = UnityObjectToClipPos(v.vertex);
                   //テクスチャとuv座標の対応付け
                   o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                   UNITY_TRANSFER_FOG(o,o.vertex);
                   return o;
               }

               float rand(float2 co){
                   return frac(sin(dot(co.xy, fixed2(12.9898,78.233))) * 43758.5453);
               }

               fixed4 frag (v2f i) : SV_Target
               {
                   float s = _Time * 20;
                   float2 p = i.uv * 2.0 - 1.0;//正規化
                   float c = rand(p);//各座標ごとにランダムな値を生成
                   float2 q = float2(c, c);
                   //ランダム値によって星の明るさの初期値を設定。また、時間によって星の明るさが変動:0.5~1.5
                   float l = 0.01/length(q) * abs(sin(s) * 0.5 + 1.0);
                   fixed4 col = float4( 33/255.0 + l, 32/255.0 + l, 142.0/255.0 + l, 1.0);

                   UNITY_APPLY_FOG(i.fogCoord, col);

                   return col;
               }
               ENDCG
           }

           GrabPass{}

           //パーリンノイズつくってる
           Pass {
           //Blend SrcAlpha OneMinusSrcAlpha // Alpha blending
           //Blend One One // Additive
           //Blend OneMinusDstColor One // Soft Additive
           Blend DstColor Zero // Multiplicative
           //Blend DstColor SrcColor // 2x Multiplicative
           CGPROGRAM
               #pragma vertex vert
               #pragma fragment frag
               // make fog work
               #pragma multi_compile_fog

               #include "UnityCG.cginc"

               struct appdata
               {
                   float4 vertex : POSITION;
                   float2 uv : TEXCOORD0;
               };

               struct v2f
               {
                   float2 uv : TEXCOORD0;
                   UNITY_FOG_COORDS(1)
                   float4 vertex : SV_POSITION;
               };

               sampler2D _GrabTexture;
               float4 _GrabTexture_ST;

               float Circle(float2 p){
                   p*= 10.0;

                   return ((p.x*p.x+p.y*p.y)-10);
               }

               v2f vert (appdata v)
               {
                   v2f o;
                   o.vertex = UnityObjectToClipPos(v.vertex);
                   o.uv = TRANSFORM_TEX(v.uv, _GrabTexture);
                   UNITY_TRANSFER_FOG(o,o.vertex);
                   return o;
               }

               float rand(float3 co){
                   return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 56.787))) * 43758.5453);
               }

               float rings(float2 p){
                   return sin(length(p)*100);
               }

               float noise(float3 pos){
                   float3 ip = floor(pos);
                   float3 fp = smoothstep(0, 1, frac(pos));
                   //smoothstep関数
                   //x<minの時、0を返す
                   //max>xの時、1を返す
                   //min<=x<maxの時、0から1の間の滑らかな値を返す
                   float4 a = float4(
                   rand(ip + float3(0, 0, 0)),
                   rand(ip + float3(1, 0, 0)),
                   rand(ip + float3(0, 1, 0)),
                   rand(ip + float3(1, 1, 0)));
                   float4 b = float4(
                   rand(ip + float3(0, 0, 1)),
                   rand(ip + float3(1, 0, 1)),
                   rand(ip + float3(0, 1, 1)),
                   rand(ip + float3(1, 1, 1)));
                   a = lerp(a, b, fp.z);
                   a.xy = lerp(a.xy, a.zw, fp.y);
                   return lerp(a.x, a.y, fp.x);
               }

               float perlin(float3 pos,float time){
                   return 
                   (noise(pos) * 32 +
                   noise(pos * 2 ) * 16 +
                   noise(pos * 4) * 8 +
                   noise(pos * 8) * 4 +
                   noise(pos * 16 - s) * 2 +
                   noise(pos * 32 + s) ) / 63;
               }


               fixed4 frag (v2f i) : SV_Target
               {

                   float s = 0;
                   float4 col = float4(perlin (float3(i.uv,0),s),perlin (float3(i.uv,0),s),perlin (float3(i.uv,0),s),1);

                   return col;
               }
               ENDCG
           }
       }

   }

今回は2パスで作ってみた。
1パス目で背景色と星っぽい点を描画、2パス目でパーリンノイズをBlendして星雲っぽい感じを出してみた。

基本的にはfrag関数をいじれば描画されるものを操作できるのかな?
という印象を受けた。完成図を想像しながら色々いじっていくのは結構面白かった。

次はもう少し複雑な絵を作ってみたい。
あと、今回はunlit shaderで作成したけど、standard surface shaderとどっちが一般的に使われてるのかも調べたい。

※参考

[連載]やってみれば超簡単! WebGL と GLSL で始める、はじめてのシェーダコーディング(1)

7日間でマスターするUnityシェーダ入門

Unityのshaderで動く雲っぽいやつ

この記事が気に入ったらサポートをしてみませんか?