294 lines
9.3 KiB
HLSL
294 lines
9.3 KiB
HLSL
|
#ifndef POI_VORONOI
|
||
|
#define POI_VORONOI
|
||
|
|
||
|
#include "CGI_PoiRNG.cginc"
|
||
|
|
||
|
uint _VoronoiSpace;
|
||
|
uint _VoronoiBlend;
|
||
|
uint _VoronoiType;
|
||
|
float4 _VoronoiColor0;
|
||
|
float _VoronoiEmission0;
|
||
|
float4 _VoronoiColor1;
|
||
|
float _VoronoiEmission1;
|
||
|
float2 _VoronoiGradient;
|
||
|
float _VoronoiScale;
|
||
|
float3 _VoronoiSpeed;
|
||
|
int _VoronoiOctaveNumber;
|
||
|
float _VoronoiOctaveScale;
|
||
|
float _VoronoiOctaveAttenuation;
|
||
|
float _VoronoiEnableRandomCellColor;
|
||
|
float2 _VoronoiRandomMinMaxSaturation;
|
||
|
float2 _VoronoiRandomMinMaxBrightness;
|
||
|
float3 randomPoint;
|
||
|
|
||
|
POI_TEXTURE_NOSAMPLER(_VoronoiMask);
|
||
|
POI_TEXTURE_NOSAMPLER(_VoronoiNoise);
|
||
|
float _VoronoiNoiseIntensity;
|
||
|
|
||
|
float2 inoise(float3 P, float jitter)
|
||
|
{
|
||
|
float3 Pi = mod(floor(P), 289.0);
|
||
|
float3 Pf = frac(P);
|
||
|
float3 oi = float3(-1.0, 0.0, 1.0);
|
||
|
float3 of = float3(-0.5, 0.5, 1.5);
|
||
|
float3 px = Permutation(Pi.x + oi);
|
||
|
float3 py = Permutation(Pi.y + oi);
|
||
|
|
||
|
float3 p, ox, oy, oz, dx, dy, dz;
|
||
|
float2 F = 1e6;
|
||
|
|
||
|
for (int i = 0; i < 3; i ++)
|
||
|
{
|
||
|
for (int j = 0; j < 3; j ++)
|
||
|
{
|
||
|
p = Permutation(px[i] + py[j] + Pi.z + oi); // pij1, pij2, pij3
|
||
|
|
||
|
ox = frac(p * K) - Ko;
|
||
|
oy = mod(floor(p * K), 7.0) * K - Ko;
|
||
|
|
||
|
p = Permutation(p);
|
||
|
|
||
|
oz = frac(p * K) - Ko;
|
||
|
|
||
|
dx = Pf.x - of[i] + jitter * ox;
|
||
|
dy = Pf.y - of[j] + jitter * oy;
|
||
|
dz = Pf.z - of + jitter * oz;
|
||
|
|
||
|
float3 d = dx * dx + dy * dy + dz * dz; // dij1, dij2 and dij3, squared
|
||
|
|
||
|
//Find lowest and second lowest distances
|
||
|
for (int n = 0; n < 3; n ++)
|
||
|
{
|
||
|
if (d[n] < F[0])
|
||
|
{
|
||
|
F[1] = F[0];
|
||
|
F[0] = d[n];
|
||
|
randomPoint = p;
|
||
|
}
|
||
|
else if(d[n] < F[1])
|
||
|
{
|
||
|
F[1] = d[n];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return F;
|
||
|
}
|
||
|
|
||
|
float voronoi2D(in float2 x, float scale, float2 speed)
|
||
|
{
|
||
|
x *= scale;
|
||
|
x += speed * _Time.x;
|
||
|
float2 n = floor(x);
|
||
|
float2 f = frac(x);
|
||
|
|
||
|
// first pass: regular voronoi
|
||
|
float2 mg, mr;
|
||
|
float md = 8.0;
|
||
|
for (int j = -1; j <= 1; j ++)
|
||
|
{
|
||
|
for (int i = -1; i <= 1; i ++)
|
||
|
{
|
||
|
float2 g = float2(float(i), float(j));
|
||
|
float2 o = random2(n + g);
|
||
|
float2 currentPoint = o;
|
||
|
|
||
|
float2 r = g + o - f;
|
||
|
float d = dot(r, r);
|
||
|
|
||
|
if (d < md)
|
||
|
{
|
||
|
md = d;
|
||
|
mr = r;
|
||
|
mg = g;
|
||
|
randomPoint.xy = currentPoint;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// second pass: distance to borders
|
||
|
md = 8.0;
|
||
|
for (int r = -2; r <= 2; r ++)
|
||
|
{
|
||
|
for (int q = -2; q <= 2; q ++)
|
||
|
{
|
||
|
float2 g = mg + float2(float(q), float(r));
|
||
|
float2 o = random2(n + g);
|
||
|
|
||
|
float2 r = g + o - f;
|
||
|
|
||
|
if (dot(mr - r, mr - r) > 0.00001)
|
||
|
{
|
||
|
md = min(md, dot(0.5 * (mr + r), normalize(r - mr)));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return md;
|
||
|
}
|
||
|
|
||
|
float voronoi3D(in float3 x, float scale, float3 speed)
|
||
|
{
|
||
|
x *= scale;
|
||
|
x += speed * _Time.x;
|
||
|
float3 n = floor(x);
|
||
|
float3 f = frac(x);
|
||
|
|
||
|
// first pass: regular voronoi
|
||
|
float3 mg, mr;
|
||
|
float md = 8.0;
|
||
|
for (int j = -1; j <= 1; j ++)
|
||
|
{
|
||
|
for (int i = -1; i <= 1; i ++)
|
||
|
{
|
||
|
for (int h = -1; h <= 1; h ++)
|
||
|
{
|
||
|
float3 g = float3(float(h), float(i), float(j));
|
||
|
float3 o = random3(n + g);
|
||
|
float3 currentPoint = o;
|
||
|
|
||
|
float3 r = g + o - f;
|
||
|
float d = dot(r, r);
|
||
|
|
||
|
if (d < md)
|
||
|
{
|
||
|
md = d;
|
||
|
mr = r;
|
||
|
mg = g;
|
||
|
randomPoint = currentPoint;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// second pass: distance to borders
|
||
|
md = 8.0;
|
||
|
for (int r = -2; r <= 2; r ++)
|
||
|
{
|
||
|
for (int q = -2; q <= 2; q ++)
|
||
|
{
|
||
|
for (int p = -2; p <= 2; p ++)
|
||
|
{
|
||
|
float3 g = mg + float3(float(p), float(q), float(r));
|
||
|
float3 o = random3(n + g);
|
||
|
|
||
|
float3 r = g + o - f;
|
||
|
|
||
|
if (dot(mr - r, mr - r) > 0.00001)
|
||
|
{
|
||
|
md = min(md, dot(0.5 * (mr + r), normalize(r - mr)));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return md;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// fracal sum, range -1.0 - 1.0
|
||
|
float VoronoiNoise_Octaves(float3 p, float scale, float3 speed, int octaveNumber, float octaveScale, float octaveAttenuation, float jitter, float time)
|
||
|
{
|
||
|
float freq = scale;
|
||
|
float weight = 1.0f;
|
||
|
float sum = 0;
|
||
|
for (int i = 0; i < octaveNumber; i ++)
|
||
|
{
|
||
|
float2 F = inoise(p * freq + time * speed, jitter) * weight;
|
||
|
|
||
|
sum += sqrt(F[0]);
|
||
|
|
||
|
freq *= octaveScale;
|
||
|
weight *= 1.0f - octaveAttenuation;
|
||
|
}
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
float VoronoiNoiseDiff_Octaves(float3 p, float scale, float3 speed, int octaveNumber, float octaveScale, float octaveAttenuation, float jitter, float time)
|
||
|
{
|
||
|
float freq = scale;
|
||
|
float weight = 1.0f;
|
||
|
float sum = 0;
|
||
|
for (int i = 0; i < octaveNumber; i ++)
|
||
|
{
|
||
|
float2 F = inoise(p * freq + time * speed, jitter) * weight;
|
||
|
|
||
|
sum += sqrt(F[1]) - sqrt(F[0]);
|
||
|
|
||
|
freq *= octaveScale;
|
||
|
weight *= 1.0f - octaveAttenuation;
|
||
|
}
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
void applyVoronoi(inout float4 finalColor, inout float3 VoronoiEmission)
|
||
|
{
|
||
|
_VoronoiOctaveNumber = 1;
|
||
|
_VoronoiOctaveScale = 1;
|
||
|
_VoronoiOctaveAttenuation = 1;
|
||
|
randomPoint = 0;
|
||
|
|
||
|
float voronoi = 0;
|
||
|
|
||
|
float3 position = 0;
|
||
|
|
||
|
UNITY_BRANCH
|
||
|
if (_VoronoiSpace == 0)
|
||
|
{
|
||
|
position = poiMesh.localPos;
|
||
|
}
|
||
|
UNITY_BRANCH
|
||
|
if(_VoronoiSpace == 1)
|
||
|
{
|
||
|
position = poiMesh.worldPos;
|
||
|
}
|
||
|
UNITY_BRANCH
|
||
|
if(_VoronoiSpace == 2)
|
||
|
{
|
||
|
position = float3(poiMesh.uv[0].x, poiMesh.uv[0].y, 0);
|
||
|
}
|
||
|
|
||
|
float mask = POI2D_SAMPLER_PAN(_VoronoiMask, _MainTex, poiMesh.uv[_VoronoiMaskUV], _VoronoiMaskPan).r;
|
||
|
float edgeNoise = POI2D_SAMPLER_PAN(_VoronoiNoise, _MainTex, poiMesh.uv[_VoronoiNoiseUV], _VoronoiNoisePan).r * _VoronoiNoiseIntensity;
|
||
|
|
||
|
UNITY_BRANCH
|
||
|
if(_VoronoiType == 0) // Basic
|
||
|
{
|
||
|
voronoi = voronoi2D(position.xy, _VoronoiScale, _VoronoiSpeed);
|
||
|
}
|
||
|
UNITY_BRANCH
|
||
|
if (_VoronoiType == 1) // Diff
|
||
|
{
|
||
|
voronoi = VoronoiNoiseDiff_Octaves(position, _VoronoiScale, _VoronoiSpeed, _VoronoiOctaveNumber, _VoronoiOctaveScale, _VoronoiOctaveAttenuation, 1, _Time.x);
|
||
|
}
|
||
|
UNITY_BRANCH
|
||
|
if (_VoronoiType == 2) // Fixed Border
|
||
|
{
|
||
|
voronoi = voronoi3D(position, _VoronoiScale, _VoronoiSpeed);
|
||
|
// isolines
|
||
|
//color = c.x * (0.5 + 0.5 * sin(64.0 * c.x)) * 1.0;
|
||
|
}
|
||
|
|
||
|
if (_VoronoiEnableRandomCellColor == 1)
|
||
|
{
|
||
|
float3 rando = random3(randomPoint);
|
||
|
fixed hue = rando.x;
|
||
|
fixed saturation = lerp(_VoronoiRandomMinMaxSaturation.x, _VoronoiRandomMinMaxSaturation.y, rando.y);
|
||
|
fixed value = lerp(_VoronoiRandomMinMaxBrightness.x, _VoronoiRandomMinMaxBrightness.y, rando.z);
|
||
|
float3 hsv = float3(hue, saturation, value);
|
||
|
_VoronoiColor1.rgb = HSVtoRGB(hsv);
|
||
|
}
|
||
|
_VoronoiGradient.xy += edgeNoise;
|
||
|
float ramp = smoothstep(_VoronoiGradient.x, _VoronoiGradient.y, voronoi);
|
||
|
|
||
|
UNITY_BRANCH
|
||
|
if(_VoronoiBlend == 0)
|
||
|
{
|
||
|
float4 voronoiColor = lerp(_VoronoiColor0, _VoronoiColor1, ramp);
|
||
|
finalColor.rgb = lerp(finalColor.rgb, voronoiColor, mask * voronoiColor.a);
|
||
|
}
|
||
|
float4 voronoiEmissionColor = lerp(_VoronoiColor0 * _VoronoiEmission0, _VoronoiColor1 * _VoronoiEmission1, ramp);
|
||
|
VoronoiEmission = voronoiEmissionColor.rgb * mask * voronoiEmissionColor.a;
|
||
|
}
|
||
|
|
||
|
#endif
|