You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.1 KiB
Plaintext

shader_type spatial;
render_mode cull_disabled;
//uniform int _ShellIndex; // index of shell being worked on (0 -> _ShellCount)
uniform float _NoiseMin; // minimum strand length
uniform float _NoiseMax; // maxmimum strand length
uniform float _ShellLength; // amount of distance that the shells cover, 1 means shells will span across 1 world space unit
uniform int _ShellCount; // total number of shells (for normalizing the shell index)
uniform float _ShellDistanceAttenuation; // exponent how far to push the shell outwards
uniform float _Thickness; // how thick a strand shall be
uniform float _Attenuation; // AO strength factor
uniform float _OcclusionBias; // additive bias for AO
uniform vec3 _ShellColor;
uniform float _Density; // amout of strands to generate
varying flat int _ShellIndex;
float hash(uint n) {
n = (n << 13U) ^ n;
n = n * (n * n * 15731U + 1239221U) + 123376312589U;
return float(n & uint(0x7fffffffU)) / float(0x7fffffff);
}
void vertex() {
_ShellIndex = int(INSTANCE_CUSTOM.x);
float shell_height = float(_ShellIndex) / float(_ShellCount);
shell_height = pow(shell_height, _ShellDistanceAttenuation);
VERTEX.xyz += NORMAL.xyz * _ShellLength * shell_height;
//NORMAL = normalize(NORMAL);
UV = UV;
}
void fragment() {
vec2 newUV = UV * _Density;
vec2 localUV = fract(newUV) * 2. - 1.;
float localDistanceFromCenter = length(localUV);
float h = float(_ShellIndex) / float(_ShellCount); // normalized height
uint seed = uint(int(newUV.x) + 100 * int(newUV.y) + 100 * 10);
float rand = mix(_NoiseMin, _NoiseMax, hash(seed)); // getting random value for strand
if (localDistanceFromCenter > _Thickness * (rand - h) && _ShellIndex > 0) discard; // discarding pixels outside of thickness
//float ndotl = dot(NORMAL, WORLD) // TODO do light later?
float ambientOcclusion = pow(h, _Attenuation); // fake Ambient Occlusion
ambientOcclusion += _OcclusionBias;
// Called for every pixel the material is visible on.
ALBEDO.rgb = _ShellColor * ambientOcclusion;
//ALPHA = 1.0;
}
void light() {
float ndotl = clamp(dot(NORMAL, LIGHT), 0., 1.) * .5 + .5;
DIFFUSE_LIGHT += ndotl * ndotl;
}