しゅみぷろ

プログラミングとか

InkPainterがリリースされました

おしらせ

InkPainterを正式にGitHubおよびAssetStoreで公開しました。

GitHub - EsProgram/InkPainter: Texture-Paint on Unity. Asset Store

もともとUnityTexturePaintとして販売し、国内外様々な方から色々な意見、レビューをいただいていたのですが、ある時期にAssetStoreから「似たような名前のプロダクトが既に存在し、混乱を招くので」ということで、AssetStoreから削除されてしまいました。

Textureにペイントを行えるプロダクトは確かにいくつかあるのですが、プロダクトごとに個性があるので、AssetStoreでの公開は辞めたくないなと思い、リネーム等の作業を行いリリースし直したのがInkPainterになります。

この作業に伴い、主にディレクトリ構造、ネームスペース、クラス名等改修が入っていますので、ご注意ください。

また、ドキュメントのURLも変更になりました。 InkPainter: Main Page

UnityTexturePaintをご利用下さっていた皆様にはご迷惑をお掛けして、大変申し訳ございません。

新しくなったInkPainterをご利用いただき、ご意見いただけましたら幸いです。

できること

ランタイムにテクスチャへの書き込みが可能になります。 InkPainterと名付けたので、インクっぽさを追求していくつもりです。 例えばこんなことができます。

f:id:es_program:20170401115516g:plain:w420


Unity Texture Paint

雨の日カメラ with Unity

今後の事

さて、お知らせという事でお堅い文章ズラズラと書きなぐりましたが、ここからは今後のリリース予定についてザックリとメモしていきます。こうする事で、僕が開発から逃げる可能性が減ります。

  • Inspectorに表示されるUIのカスタマイズ
  • ブラシ画像を回転させて塗布する機能の追加
  • 動画によるHow toや応用事例紹介
  • ComputeShader実行可能環境におけるペイント処理にGPGPUを用いた高速化が望めそうならば実装

因みに現在ComputeShaderが利用可能な環境は以下のようになります(https://docs.unity3d.com/ja/540/Manual/ComputeShaders.html より引用)

Mac OS XOpenGL 4.3 に対応していないため、コンピュートシェーダーはまだ利用できません。

ここらへん効果があるのか、効果があるとしたらどの程度なのかが詳しく分かっていません。ペイントを施す場合、たとえ同じマテリアルのオブジェクトが2つあったとしても、テクスチャを別物として扱う必要があり、マテリアルのコピーが発生するため、バッチングが効かなくなります。オブジェクトが多すぎて描画処理のネックとなるのがこの部分であることが大半なので、恐らく大きな効果は見込めなさそうに思います。

雨の日のカメラを作る

はじめに

カメラのレンズに雨が付着した感を出してみました。

ささっと作ったのですが、ちょっといい感じになったので自分で驚いてます。 雨粒が付着した部分は背景の映り込みが歪むようになっています。

Unity Standerd Assetに含まれるガラスシェーダーを使いまわしたので、10分くらいで実装することが出来ました。

実装方法

UnityTexturePaintを使います。

github.com

まずは以下の画像のように Assets -> Import Package -> Effectsを選択して、Glass Refractionをインポートします。 Glass Refractionでは、GrabPassで取得したテクスチャと法線マップを使い、写り込んだ背景を歪ませる処理が行われています。 このシェーダーをそのまま利用し、透明な状態で法線情報だけを更新していき、水滴が付着したように見せるという寸法です。

f:id:es_program:20170403212428p:plain:w600

次に、カメラ正面にQuadを置き、Quadのマテリアルを先程インポートしたGlassRefractiveに変更し、テクスチャを真っ白なものに差し替えます。QuadのコンポーネントにDynamicCanvasとHeightFluidをアタッチしたら準備は完了です。

f:id:es_program:20170403213207p:plain:w600

あとはTexturePaintを使って、Quadの適用な位置にHeight(液体の付着量)情報をペイントしてやります。

具体的には

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Es.TexturePaint;

public class RainPainter : MonoBehaviour
{
    [SerializeField]
    private DynamicCanvas canvas;

    [SerializeField]
    private PaintBrush brush;

    [SerializeField]
    private float minSize;

    [SerializeField]
    private float maxSize;

    [SerializeField, Range(0, 100)]
    private float aboutCallPercentOnFrame = 10;

    private void OnWillRenderObject()
    {
        if(Random.Range(0f, 100f) > aboutCallPercentOnFrame)
            return;

        for(int i=Random.Range(1, 10);i>0;--i){
            brush.Scale = Random.Range(minSize, maxSize);
            canvas.PaintUVDirect(brush, new Vector2(Random.Range(0f, 1f), Random.Range(0f, 1f)));
        }
    }
}

こんなスクリプトを書いてQuadに取り付けて、BrushTextureとBrushHeightTextureにこんな感じの画像を与えてやります(透過済みの画像です)。

f:id:es_program:20170403213616p:plain:w200

サンプルの動画では設定はこんな感じに。

f:id:es_program:20170403213745p:plain:w400

あとは実行すれば、適当な位置に水滴がついたような効果が断続的に出現します。

最後に

1粒1粒の水滴がつくたびに描画命令を発行するため、今回のままではパフォーマンス的によろしくありません。 改善する方法としては、水滴がたくさん付いているようなテクスチャを入力として、1回で複数の雨粒を書き込んでやる、などが挙げられます。