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
62 lines
2.1 KiB
Plaintext
9 months ago
|
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;
|
||
|
}
|