44
43

More than 5 years have passed since last update.

【Unity】シェーダーで面を凸凹(デコボコ)する方法【Tessellation・Displacement】

Last updated at Posted at 2019-01-27

shaderの勉強をしていると、こんな疑問が出てきませんか?

テクスチャの明度に応じて、面をデコボコさせたいけど、どうすればよいんだ?

ツール(Shader Graph, Shader Forge)を使って、面を凸凹するシェーダーを作成するやり方はwebに色々あるんですが、ツールなしの方法が見当たない…

途方に暮れていたのですが、奇跡的に知り合ったUnityコミュニティに質問したところ、やり方が判明したので、ご紹介します。サンプルソースもありますよ!

ちなみに、タイトルは私のように”シェーダー 平面 凸凹(でこぼこ)”とググっても出てくるように設定しました笑

※追記 2019/1/28
ここでは、頂点を上下させて面を凸凹させる方法をご紹介します。他にも、凹凸が「あるように」見せるバンプマッピングという手法がございます。こちらの方法は、以下の記事をご覧ください。
[Unity] バンプマッピング(法線マッピング)をやってみる

結論:できる!!!

結論から述べると、ツール無しでもシェーダーで平面を凸凹することはできます!

じゃぁ、なぜ”シェーダー 平面 凸凹(でこぼこ)”とググっても出てこないか?

それは平面を凸凹する方法は専門用語で存在しており、みんな専門用語で紹介しているからなんですね。なので、専門用語を知らないと、答えには辿り着かないという(^p^)

キーワードはTessellation・Displacement!

平面凸凹のキーワードは2つです!

  • Tessellation(テッセレーション):ポリゴンメッシュを細分割
  • Displacement(ディスプレイス):テクスチャの高さマップを描画時に評価して頂点を上下

テッセレーションでメッシュを再分割し、凹凸しやすくしてから、ディスプレイス(頂点を上下)します。イメージはこんな感じです!

サンプルソース

やらたいことがわかっても、肝心なソースがなければ、実装できないですよね。ご安心ください。

なんと、公式が提供している"Standard Assets"にあるんです(マジで神)

ソースの場所と中身がこちら!
スクリーンショット 2019-01-27 10.08.28.png
スクリーンショット 2019-01-27 10.08.35.png
スクリーンショット_2019-01-27_10_12_37.png

インポート後、Assets > Standard Assets > Effects > TessellationShadersにシェーダーやマテリアファイルが入っています!

ソースの中身はこんな感じ!

pedSpecularDisplacement.shader
Shader "Tessellation/Bumped Specular (displacement)" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    _Shininess ("Shininess", Range (0.03, 1)) = 0.078125
    _Parallax ("Height", Range (0.0, 1.0)) = 0.5
    _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
    _BumpMap ("Normalmap", 2D) = "bump" {}
    _ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    _EdgeLength ("Edge length", Range(3,50)) = 10
}
SubShader { 
    Tags { "RenderType"="Opaque" }
    LOD 800

CGPROGRAM
#pragma surface surf BlinnPhong addshadow vertex:disp tessellate:tessEdge
#include "Tessellation.cginc"

struct appdata {
    float4 vertex : POSITION;
    float4 tangent : TANGENT;
    float3 normal : NORMAL;
    float2 texcoord : TEXCOORD0;
    float2 texcoord1 : TEXCOORD1;
    float2 texcoord2 : TEXCOORD2;
};

float _EdgeLength;
float _Parallax;

float4 tessEdge (appdata v0, appdata v1, appdata v2)
{
    return UnityEdgeLengthBasedTessCull (v0.vertex, v1.vertex, v2.vertex, _EdgeLength, _Parallax * 1.5f);
}

sampler2D _ParallaxMap;

void disp (inout appdata v)
{
    float d = tex2Dlod(_ParallaxMap, float4(v.texcoord.xy,0,0)).a * _Parallax;
    v.vertex.xyz += v.normal * d;
}

sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
half _Shininess;

struct Input {
    float2 uv_MainTex;
    float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
    fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    o.Albedo = tex.rgb * _Color.rgb;
    o.Gloss = tex.a;
    o.Alpha = tex.a * _Color.a;
    o.Specular = _Shininess;
    o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}

FallBack "Bumped Specular"
}

マテリアルをアタッチすると、凸凹した面ができあがります!
(マテリアルもインポートしたスタンダードアセット内にあります)
unity_qiita.gif

最後に

Tessellation・Displacementを使えば、シェーダーで面を凸凹できます。凸凹はテクスチャによるので、種類は無限大!

平面以外にも、棒などの様々なオブジェクトを凸凹したい時にも使えるので便利です。

公式のシェーダーを使えば簡単に実装できるので、ぜひ気になる方はお試しください!

参考記事

44
43
3

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
44
43