1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unity デッサン風 ポストエフェクト

Posted at

作ったもの

drawing.gif

アルゴリズムの概要

  1. C# スクリプトで画面全体に広がるパーリンノイズのテクスチャを生成。
  2. ポストエフェクトシェーダで各ピクセルの明度を計算。
  3. 明度をいくつかの段階に分割して、各段階に応じてパーリンノイズのテクスチャに係数をかけて色をピックアップ。

もう知られているやり方だったらすみません

ソースコード

C#

using System.Collections;
using UnityEngine;

public class DrawingTextureGenerator : MonoBehaviour
{
	Texture2D m_texture;

	[SerializeField] int m_scale;
	[SerializeField] float m_power;
	[SerializeField] float m_cor = 1;
	[SerializeField] Material m_postEffectMat;
	[SerializeField] float m_scaleX = 1;
	[SerializeField] float m_scaleY = 1;

	private void Awake()
	{
		int w = Screen.width;
		int h = Screen.height;
		m_texture = new Texture2D(w, h, TextureFormat.ARGB32, false);
	}

	private void Start()
	{
		StartCoroutine(UpdateImage());
		m_postEffectMat.SetTexture("_DrawingTex", m_texture);
	}

	IEnumerator UpdateImage()
	{
		// 1. パーリンノイズテクスチャの生成
		while (true)
		{
			int w = Screen.width;
			int h = Screen.height;
			float t = Time.realtimeSinceStartup;
			for (int y = 0; y < h; y++)
			{
				for (int x = 0; x < w; x++)
				{
					float sample = Mathf.PerlinNoise((float)x / w * m_scale * m_scaleX + Random.value, (float)y / h * m_scale * m_scaleY);
					sample = Mathf.Pow(sample, m_power) * m_cor;
					m_texture.SetPixel(x, y, new Color(sample, sample, sample));

					if(Time.realtimeSinceStartup - t >= 1.0f / 60.0f)
					{
						yield return null;
						t = Time.realtimeSinceStartup;
					}
				}
			}

			m_texture.Apply();
		}
	}
}


シェーダ

Shader "Hidden/Drawing"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _DrawingTex ("Drawing", 2D) = "white" {}
        _Threshold1 ("Threshold1", Float) = 0
        _Threshold2 ("Threshold2", Float) = 0
        _Threshold3 ("Threshold3", Float) = 0
        _Threshold4 ("Threshold4", Float) = 0

        _Magni1 ("Magni1", Float) = 0
        _Magni2 ("Magni2", Float) = 0
        _Magni3 ("Magni3", Float) = 0
        _Magni4 ("Magni4", Float) = 0

        _Xdiff ("Xdiff", Float) = 0
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

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

            sampler2D _MainTex;
            sampler2D _DrawingTex;
            float _Threshold1;
            float _Threshold2;
            float _Threshold3;
            float _Threshold4;
            float _Magni1;
            float _Magni2;
            float _Magni3;
            float _Magni4;

            float _Xdiff;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                // 2. ピクセルの明度を計算
                half brightness = dot(col, half3(0.299, 0.587, 0.114));
                
                // 3. 明度に応じてパーリンノイズのテクスチャに係数をかけて色をピックアップ
                fixed4 drawingCol = tex2D(_DrawingTex, float2(i.uv.x + _Xdiff * i.uv.y, i.uv.y));
                if(brightness >= 0.9){
                    drawingCol = 1;
                } else if (brightness >= _Threshold1){
                    drawingCol *= _Magni1;
                } else if (brightness >= _Threshold2){
                    drawingCol *= _Magni2;
                } else if (brightness >= _Threshold3){
                    drawingCol *= _Magni3;
                }else if(brightness >= _Threshold4){
                    drawingCol *= _Magni4;
                }
                return drawingCol;
            }
            ENDCG
        }
    }
}


パーリンノイズのテクスチャから色をピックアップする際に斜めにずらすことで、デッサン感を出しています。
また、パーリンノイズテクスチャの生成時に X 座標値をランダムにずらしています。こうした方がいい感じに見えたので。
冒頭の gif 画像のようにするパラメータは以下の通りです。

image.png

image.png

パーリンノイズの生成が重いので、実際にゲームで使う場合には一度作ったものを使いまわすと良いかと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?