【Unity】ShaderGraphで虹色に光らすShaderを作成する

はじめに

バージョン Unity 2019.3.0f3

Universal Render Pipeline使用

こんな感じの虹色に光るshaderを作成していきます。

シェーダーグラフはUnlit Graphで作成します。

枠線の作成

2つの矩形をRectangleノードで作成してそれを減算して枠線を作成します。

虹色に光る部分に作成

Gradientノードで虹色のグラデーションを作成し、

それをRotateノードで回転させることで虹色に光ってるように見せています。

あとは適当にEmission用Vector1ノードを作成して発行具合を調整してる感じです。

完成図

これで完成です。

このやり方だと均等にグラデーションが回転されません。 均等にやるやり方はこちら

bravememo.hatenablog.com

今回作成したシェーダーはBoothで公開しています braveshop.booth.pm

bravememo.hatenablog.com

【MSBuild】ビルド構成の切り替えを自動化してまとめてビルドする

目次

MSBuildとは

.NET Framework 2.0から同梱されいるビルド環境です。 Visual Studioがインストールしなくても実行できるのがいいところで、 jenkinsやbatファイルから呼び出して自動でビルドをかけたりすることができます。

参考URL

www.atmarkit.co.jp

目的

複数のビルド構成のexeが必要だと、ビルド構成切り替え→ビルドする作業が何回もやらないといけない場合があり、面倒なので自動化して指定したビルド構成全部をビルドして楽するために作成する。

※どんなビルド構成のexeが必要かというと、

たとえばデバック用のexeリリース用のexeやフルスクリーンをオンにした状態のexeとか、プロジェクトによってさまざまなexeの提出を求められることがあります。

visual studio側の準備

プロジェクトの用意

今回はvisual studio2015の

c++のwin32コンソールアプリケーションでプロジェクト作成します。

f:id:Brave345:20200207155705p:plain

ターゲット名の変更

今回は元からあるデバックとリリースのビルド構成を使用しますが、exeの名前が同じだとわかりづらいのでデバックの方だけexeの名前を変えます。

名前はプロジェクト名_Debug.exeになります。

f:id:Brave345:20200207155718p:plain

ソースコード

ビルド構成によって出力される文字が変わるだけのシンプルな奴です。

// ConsoleApplication1.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <cstdlib>

int main()
{
#ifdef _DEBUG
    puts("Debug");
#else
    puts("Release");
#endif

    system("PAUSE");
    return 0;
}

MSBuildを使ったbatファイルを作成

ConsoleApplication1.slnと同じ階層に以下のbatファイルを用意します。

title %date% %time% ROM生成

@echo off
rem このbatをカレントディレクトリとする----------------------------------------
cd /d %~dp0

echo masterROMを生成を開始します
  
rem フォルダの生成-------------------------------------------------------------
if exist ROM (
    echo ROMフォルダは存在してます
) else (
    echo ROMフォルダを生成します
    md ROM
)

rem ビルド設定--------------------------------------------------------------------------
@Set Path=C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319;%PATH%


rem デバックビルド実行------------------------------------------------------------------
echo デバックビルド実行します
msbuild ConsoleApplication1.sln /p:Configuration=Debug /t:Rebuild /p:Platform="x86"

echo Exeデータを複製
copy /y Debug\ConsoleApplication1_Debug.exe ROM\ConsoleApplication1_Debug.exe


rem リリースビルド実行------------------------------------------------------------------
echo リリースビルド実行します
msbuild ConsoleApplication1.sln /p:Configuration=Release /t:Rebuild /p:Platform="x86"

echo Exeデータを複製
copy /y Release\ConsoleApplication1.exe ROM\ConsoleApplication1.exe



exit /B

ビルド構成を変えたいときは/p:Configuration=〇〇の部分を変更すればいいです。

このbatファイルを起動すると以下のようになります。

f:id:Brave345:20200207155744p:plain

これでbatファイルからデバックとリリースのexeが一気に作成することができました。

終わりに

今回作成したプロジェクトはgithubで公開してます。 気になったかたはどうぞ。

github.com

もしうまく起動しなかったらMicrosoft.NET\Frameworkのバージョンを確認してください。

C# カーブエディタ進捗 プレビュー機能作成

前の記事

bravememo.hatenablog.com

完成図

だいぶレイアウトが変わりました。


CurveEditor ver 1 プレビュー機能追加

プレビュー機能作成

作成したグラフを使うとどのような挙動をするのかをすぐに確認できたらいいなーと思い作りました。

グラフの値に応じて黒い四角形が移動、回転、拡大縮小、フェードインフェードアウトを行うようにしました。

拡大縮小の実装方法はこちら

bravememo.hatenablog.com

描画更新のタイミング変更

いままではなにかの値が変わるたびに描画を更新してました。

ですがその実装だと複数の値が同時に変わった時に無駄な描画を更新するのを対策しないといけないため実装がすこし大変でした。

そこでゲームと同じように1/60秒ごとに描画を更新することで描画の更新タイミングを気にしなくていいようになりました。

public Form1()
{
      CompositionTarget.Rendering += RenderFrame;
}

//再生中の挙動
 private void RenderFrame(object sender, EventArgs e)
 {
        m_preview.Update();
        pictureBox1.Refresh();//再描画(グラフ用);
        pictureBox4.Refresh();//再描画(回転用);
          
 }

ソースコード

プレビュー機能部分だけ

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
namespace CurveEditor
{
    class Preview
    {
        double m_TotalTime = 0;//動いている時間
        double m_MoveTime = 1000;//一回の卯木気にかける時間
        double m_MoveRatio = 0;//今どのくらい時間がたってるかの割合
        bool m_isLoop = true;//動きをループさせるか
        bool m_isInversion = false;//動きを反転させるか
        VerticalLine m_VLine;//縦線
        System.Diagnostics.Stopwatch m_Stopwatch = new Stopwatch(); //時間を測る
        PointRender m_PointRender;//グラフを読み込む機能
        int movecnt = 0;//何フレーム目
        const decimal EndPosX = 470;
        const int PictureBoxSize = 50;//画像サイズ
        PictureBox[] m_PictureBox = new PictureBox[4];

        int m_NextScale = 0;//次の画像サイズ
        float m_NextAngle = 0;//次の画像の角度

        Image img2 = Properties.Resources.yazirusi;
        Bitmap bmp;
        //画像の種類
        enum ePnum
        {
            eMove = 0,
            eScale,
            eRot,
            ea,
        };
        public void SetP(PictureBox p,int i = 0)
        {
            m_PictureBox[i] = p;

        }
        public Preview()
        {
            bmp = new Bitmap(img2, 50, 50);
        }

        public void StartTimer()
        {
            m_Stopwatch.Restart();
            m_TotalTime = 0;
            FindRatio();
            m_VLine.SetX(m_MoveRatio);
            movecnt = 0;
        }

        public void StopTimer()
        {
           // m_TotalTime = 0;
            FindRatio();
            m_VLine.SetX(m_MoveRatio);
            m_Stopwatch.Reset();
        }

        //毎フレーム呼ばれる
        public void Update()
        {
            if (!m_Stopwatch.IsRunning) return;
            //端まで行ったら
            if(m_TotalTime >= m_MoveTime)
            {
                m_TotalTime = 0;
                if(m_isLoop)
                {
                    m_Stopwatch.Restart();
                    movecnt = 0;
                }
                else
                {
                    StopTimer();
                }
                return;
            }
            m_TotalTime = m_Stopwatch.ElapsedMilliseconds;
            if (movecnt == 0) m_TotalTime = 0;//一回目のデータ読み込みは強制0
            FindRatio();
            m_VLine.SetX(m_MoveRatio);
            MovePictureBox();
            movecnt++;
        }
        //グラフに沿ってPictureBoxを動かす
        public void MovePictureBox()
        {
            if (!m_Stopwatch.IsRunning) return;

            //Yを求める
            decimal y = m_PointRender.EvaluateY((decimal)m_MoveRatio);

            y = Math.Min(1, y);
            y = Math.Max(0, y);
            //移動
            int nextpos = (int)(y * EndPosX);
      
            m_PictureBox[(int)ePnum.eMove].Location = new Point(nextpos, 15);
            //スケール
            m_NextScale = (int)(y * PictureBoxSize);
            ScalingPictureBox();
            //回転
            m_NextAngle = (float)(y * 360 * 1);

            //アルファ
            int nextcolor = (int)(255 * y);
            m_PictureBox[(int)ePnum.ea].BackColor =  Color.FromArgb(nextcolor, 0,0,0);

        }

        public void FindRatio()
        {
            m_TotalTime = Math.Min(m_TotalTime, m_MoveTime);
            m_MoveRatio = m_TotalTime / m_MoveTime;
        }

        public void SetVLine(VerticalLine v)
        {
            m_VLine = v;
        }
        public void SetIsLoop(bool loop)
        {
            m_isLoop = loop;
        }
        public bool GetIsLoop()
        {
            return m_isLoop;
        }
        public void SetisInversion(bool inversion)
        {
            m_isInversion = inversion;
        }
        public void SetMoveTime(float Second)
        {
            double time = Second * 1000;
            m_MoveTime = time;
        }
        public void SetPointRender(PointRender p)
        {
            m_PointRender = p;
        }
        //次の回転取得
        public int GetScale()
        {
            return m_NextScale;
        }
        //次の角度種t九
        public float GetAngle()
        {
            return m_NextAngle;
        }
        public void Paint(Graphics g)
        {
            if (!m_Stopwatch.IsRunning) return;
 
        }
        //画像の拡大縮小
        public void ScalingPictureBox()
        {
            m_PictureBox[(int)ePnum.eScale].Height = m_NextScale;
            m_PictureBox[(int)ePnum.eScale].Width = m_NextScale;

            Point centerPos = new Point(170, 80);//中心の座標
            Point pos = new Point(0, 0);
            //中心から拡大させる
            pos.X = (centerPos.X - m_PictureBox[(int)ePnum.eScale].Width) / 2;
            pos.Y = (centerPos.Y - m_PictureBox[(int)ePnum.eScale].Height) / 2;
            m_PictureBox[(int)ePnum.eScale].Location = pos;
        }

        /// <summary>
        /// ビットマップ(Bitmap)を回転する画像取得
        /// </summary>
        /// <param name="angle">回転角度</param>
        /// <returns></returns>
        public Bitmap GetRotateBitmap( float angle =0 )
        {
            return bmp;
        }

    }
}

終わりに

次はグラフの編集機能を強化していきたいです。

次の記事