swh:1:snp:e0709176be0f75f889c92d5bf3c708601dd371a5
Raw File
Tip revision: a26bd38e4abcbfd6bf58e9a5fa424d9ceb959960 authored by Sylvain Thery on 02 December 2022, 14:10:09 UTC
update README
Tip revision: a26bd38
micro_patterns.frag
#version 300 es
precision highp float;
uniform highp sampler2D TU_noises;
uniform highp sampler2DArray TU_cm;
uniform float sc;
uniform vec2 tr;
uniform int NB_CM;
uniform int render_out;
in vec2 tc;
uniform int level_max;
uniform float aniso_level;

out vec4 frag_out;

void TriangleGrid(vec2 uv, out vec3 Bi,	out ivec2 vertex1, out ivec2 vertex2, out ivec2 vertex3)
{
	uv *= 3.464; // 2 * sqrt(3)

	const mat2 gridToSkewedGrid = mat2(1.0, 0.0, -0.57735027, 1.15470054);
	vec2 skewedCoord = gridToSkewedGrid * uv;

	ivec2 baseId = ivec2(floor(skewedCoord));
	vec3 temp = vec3(fract(skewedCoord), 0);
	temp.z = 1.0 - temp.x - temp.y;
	if (temp.z > 0.0)
	{
		Bi = temp.zyx;
		vertex1 = baseId;
		vertex2 = baseId + ivec2(0, 1);
		vertex3 = baseId + ivec2(1, 0);
	}
	else
	{
		Bi = vec3(0,1,1) - temp.zyx;
		vertex1 = baseId + ivec2(1, 1);
		vertex2 = baseId + ivec2(1, 0);
		vertex3 = baseId + ivec2(0, 1);
	}
}

vec2 hash(vec2 p)
{
	return fract(sin((p) * mat2(127.1, 311.7, 269.5, 183.3) )*43758.5453);
}

vec3 niceGradiant(float u)
{
	float v = 2.0*u;
	return mix(vec3(0,v,1.0-v),vec3(v-1.0,2.0-v,0),step(1.0,v));
}


void Tile_n_blend_NoAniso(in vec2 uv, out vec2 mean, out vec2 variance)
{
	vec3 B;
	ivec2 vertex1, vertex2, vertex3;
	TriangleGrid(uv, B,//b1, b2, b3,
		vertex1, vertex2, vertex3);

	// Assign random offset to each triangle vertex
	vec2 uv1 = uv + hash(vec2(vertex1));
	vec2 uv2 = uv + hash(vec2(vertex2));
	vec2 uv3 = uv + hash(vec2(vertex3));

	vec2 duvdx = dFdx(uv);
	vec2 duvdy = dFdy(uv);

	vec4 n1 = textureGrad(TU_noises, uv1, duvdx, duvdy);
	vec4 n2 = textureGrad(TU_noises, uv2, duvdx, duvdy);
	vec4 n3 = textureGrad(TU_noises, uv3, duvdx, duvdy);
	vec2 nu = texelFetch(TU_noises, ivec2(0), level_max).xy; 

	B = normalize(B);
	mat3x2 M = mat3x2(n1.xy-nu,n2.xy-nu,n3.xy-nu);
	mean = M*B + nu;

	B *= B;
	mat3x2 S = mat3x2(n1.zw ,n2.zw,n3.zw)/16.0; // because *16 in mipmap creation
	variance = S * B; 
}


void Tile_n_blend_Aniso_X(in vec2 uv, out vec2 mean, out vec2 variance)
{
	vec3 B;
	ivec2 vertex1, vertex2, vertex3;
	TriangleGrid(uv, B,//b1, b2, b3,
		vertex1, vertex2, vertex3);

	// Assign random offset to each triangle vertex
	vec2 uv1 = uv + hash(vec2(vertex1));
	vec2 uv2 = uv + hash(vec2(vertex2));
	vec2 uv3 = uv + hash(vec2(vertex3));

	vec2 duvdx = dFdx(uv);
	vec2 duvdy = dFdy(uv);

	float Px = length(duvdx);
	float Py = length(duvdy);
	float Pmax = max(Px,Py);
	float TW = float(textureSize(TU_noises,0).x);
	float Pmin = min(Px,Py);
	float N = min(ceil(Pmax/Pmin),aniso_level);
	float lod = log2(Pmax/N*TW);

	N = min(N,ceil(Pmax*TW));
	int NB = int (N);
	B = normalize(B);
	vec3 B2 = B*B;

	N = float(NB+1);
	vec2 sum_mean= vec2(0);
	vec2 sum_ms = vec2(0);
	vec2 dUV = (Px>Py)?duvdx:duvdy;
	for (int i=1;i<=NB;++i)
	{
		vec2 dw = dUV*(float(i)/N-0.5);
		vec4 n1 = textureLod(TU_noises, uv1+dw, lod);
		vec4 n2 = textureLod(TU_noises, uv2+dw, lod);
		vec4 n3 = textureLod(TU_noises, uv3+dw, lod);
		vec2 nu = texelFetch(TU_noises, ivec2(0), level_max).xy;

		mat3x2 M = mat3x2(n1.xy-nu,n2.xy-nu,n3.xy-nu);
		vec2 l_mean = M*B + nu;
		sum_mean += l_mean;
		mat3x2 S = mat3x2(n1.zw ,n2.zw,n3.zw)/16.0; // because *16 in mipmap creation
		sum_ms += l_mean*l_mean + S * B2; 
	}
	N=float(NB);
	mean = sum_mean / N;
	variance = sum_ms / N - mean*mean;
	
}

vec3 proceduralNoise(vec2 uv)
{
	vec2 uv_cm;
	vec2 sigm2;
	if (aniso_level<=1.0)
		Tile_n_blend_NoAniso(uv, uv_cm, sigm2);
	else
		Tile_n_blend_Aniso_X(uv, uv_cm, sigm2);
	vec2 sigma = sqrt(sigm2);
	vec2 var = clamp(sigma*256.0 ,vec2(1.0),vec2(pow(2.0,float(NB_CM))-0.1));
	vec2 flod = log2(var);
	ivec2 ilod = ivec2(floor(flod));
	vec2 t = fract(flod);
	ivec2 ilodr = ivec2(round(flod));
/*
	int il = NB_CM*ilod.y+ilod.x;
	vec3 Col0 = mix(texture(TU_cm,vec3(uv_cm,il)).rgb,texture(TU_cm,vec3(uv_cm,il+1)).rgb,t.x);
	il += NB_CM;
	vec3 Col1 = mix(texture(TU_cm,vec3(uv_cm,il)).rgb,texture(TU_cm,vec3(uv_cm,il+1)).rgb,t.x);
	vec3 Col = mix(Col0,Col1,t.y);
*/
	switch(render_out)
	{
		case 0:
			return texture(TU_cm,vec3(uv_cm, NB_CM*ilodr.y+ilodr.x)).rgb; //Col;
		case 1:
			return vec3(uv_cm.x);
		case 2:
			return vec3(uv_cm.y);
		default:
			return vec3(1,1,1);
	}
	return vec3(1,1,1);
}

void main()
{
	vec3 texel = proceduralNoise((tc+tr)*sc);

	frag_out = vec4(texel,1);
}
back to top