環境
Unity2022.2.2f1
ShaderGraph14.0.4
概要
CustomFunctionノードを使用して、標準のvoronoiノードにプラスしてエッジまでの距離を返すようにしたノード用の関数を作成してみました。
※for文を[unroll]しないと自分の環境だとバグるので入れています。
コード
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Hashes.hlsl" float2 Unity_Voronoi_RandomVector_Deterministic_float (float2 UV, float offset) { Hash_Tchou_2_2_float(UV, UV); return float2(sin(UV.y * offset), cos(UV.x * offset)) * 0.5 + 0.5; } void VoronoiWithDistance_float(float2 UV, float AngleOffset, float CellDensity, out float Out, out float Cells, out float Distance) { // first pass: regular voronoi float2 g = floor(UV * CellDensity); float2 f = frac(UV * CellDensity); float t = 8.0; float3 res = float3(8.0, 0.0, 0.0); float2 mr; [unroll] for (int y = -1; y <= 1; y++) { [unroll] for (int x = -1; x <= 1; x++) { float2 lattice = float2(x, y); float2 offset = Unity_Voronoi_RandomVector_Deterministic_float(lattice + g, AngleOffset); float d = distance(lattice + offset, f); if (d < res.x) { res = float3(d, offset.x, offset.y); Out = res.x; Cells = res.y; mr = lattice + offset - f; } } } // second pass: distance to borders float md = 8.0; [unroll] for (int y = -2; y <= 2; y++) { [unroll] for (int x = -2; x <= 2; x++) { float2 lattice = float2(x, y); float2 offset = Unity_Voronoi_RandomVector_Deterministic_float(lattice + g, AngleOffset); float2 r = lattice + offset - f; if (dot(mr - r, mr - r) > 0.0001) { md = min(md, dot(0.5 * (mr + r), normalize(r - mr))); } } } Distance = md;//float3(md, mr.x, mr.y); } void VoronoiGetBorder_float(float Distance, float Length, out float Out) { Out = 1.0 - smoothstep(0.0, Length, Distance); }
参考
Inigo Quilez :: computer graphics, mathematics, shaders, fractals, demoscene and more
【Unity】リピート感なしのテクスチャマッピングの再現【Blender】 - 夜はCGの時間
Unity Shader Graph custom node for precise voronoi borders · GitHub
[Unity] Shader Graph でノイズ関数を改造してタイリングに対応するカスタムノードを作る(改) - Qiita
わけわからない
標準のVoronoiノードが正しく動作しない。赤くなる。何でこんな結果になるのか。
コードでも赤になる。
ただしVoronoi関数のforの上に[unroll]を付けると直る。
正しいのかはわからない。
Shader "Unlit/TestVoronoi" { Properties { } CGINCLUDE //#pragma enable_d3d11_debug_symbols #include "UnityCG.cginc" // Graph Includes #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Hashes.hlsl" // Graph Functions float2 Unity_Voronoi_RandomVector_Deterministic_float (float2 UV, float offset) { Hash_Tchou_2_2_float(UV, UV); return float2(sin(UV.y * offset), cos(UV.x * offset)) * 0.5 + 0.5; } void Unity_Voronoi_Deterministic_float(float2 UV, float AngleOffset, float CellDensity, out float Out, out float Cells) { float2 g = floor(UV * CellDensity); float2 f = frac(UV * CellDensity); float t = 8.0; float3 res = float3(8.0, 0.0, 0.0); [unroll] for (int y = -1; y <= 1; y++) { [unroll] for (int x = -1; x <= 1; x++) { float2 lattice = float2(x, y); float2 offset = Unity_Voronoi_RandomVector_Deterministic_float(lattice + g, AngleOffset); float d = distance(lattice + offset, f); if (d < res.x) { res = float3(d, offset.x, offset.y); Out = res.x; Cells = res.y; } } } } void Unity_ColorspaceConversion_HSV_RGB_float(float3 In, out float3 Out) { float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); float3 P = abs(frac(In.xxx + K.xyz) * 6.0 - K.www); Out = In.z * lerp(K.xxx, saturate(P - K.xxx), In.y); } ENDCG SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { float voroValue; float voroCells; Unity_Voronoi_Deterministic_float(i.uv, 6, 5, voroValue, voroCells); fixed3 rgb; Unity_ColorspaceConversion_HSV_RGB_float(float3(voroCells, 1, 1), rgb); return fixed4(rgb, 1); } ENDCG } } }