Stylized Skin

Stylized shader that isnt just two tone lighting + fresnel , based on some shaders I saw in some mmd videos and some art techniques for painting skin

What it does:

– Adds a hue around edges of viewed model (fresnel) , sort of like subsurface scattering

– Applies a function to diffuse light to sharpen it but still leaves it a little soft

– Reduces the darkness of the shadow and mixes the shadow area to have modified HSV values

– Adds a lighter hue around the transition between light and dark areas

– Adds specular highlights with ‘warmer’ hue around them

– Soft rim light

You might need to reduce specular and fresnel depending on scene lighting , or change hue values for different skin tones

Skin textures: https://imgur.com/a/LdJrhBa

“Godette (Rigged)” (https://skfb.ly/oxZY8) by zahlenmaler is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).

“miku brazilian (fbx) + rig” (https://skfb.ly/pwtDx) by Prismxd oficial yt is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).

Shader code
// Stylized Skin shader by paperbag

shader_type spatial;
render_mode cull_back;

// UTILITY

float remap(float v, float from1, float to1, float from2, float to2) 
{
	return (v - from1) / (to1 - from1) * (to2 - from2) + from2;
}

float fresnel(float amount, vec3 normal, vec3 view)
{
	return pow((1.0 - clamp(dot(normalize(normal), normalize(view)), 0.0, 1.0)), amount);
}

// Color space conversion from https://godotshaders.com/shader/color-range-swap/
vec3 rgb2hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

vec3 shiftHSV(vec3 color, float hueChange, float saturationChange, float valueChange){
	vec3 c = rgb2hsv(color);
	
	c.r += hueChange;
	c.g *= saturationChange;
	c.b *= valueChange;
	float hue = c.r + hueChange;
	c.x = (hue < 0.0) ? hue + 1.0 : ((hue > 1.0) ? hue - 1.0 : hue);
	
	return hsv2rgb(c);
}

// UTILITY END

uniform sampler2D Diffuse: source_color;
uniform sampler2D Normal: hint_normal;
uniform float NormalDepth: hint_range(0.0, 2.0) = 0.5;

// For fine detail:
// do not use this if the material is on clothing and such
// or do but use a mask for the skin area
group_uniforms Skin;
uniform sampler2D SkinSpecular;
uniform sampler2D SkinNormal: hint_normal;
uniform float SkinScale = 10.0;
uniform float SkinDepth = 0.25;

group_uniforms Hue_Shifting;
uniform float EdgeHue: hint_range(-0.5, 0.5) = -0.025;
uniform float EdgeHueFresnel = .03;
uniform float EdgeHuePower = 12.;

uniform float LightHueMult: hint_range(-0.5, 0.5) = 0.03;
uniform float LightHuePower = 2.0;

uniform float SpecularHueMult: hint_range(-0.5, 0.5) = -0.01;
uniform float SpecularHuePower = 0.536;

group_uniforms Diffuse_Shading;
uniform float ShadowSoftness = 1.5245;
uniform float ShadowOffset: hint_range(0.0, 1.0) = .829;
uniform float ShadowAmount: hint_range(0.0, 1.0) = .74;

group_uniforms Specular_Shading;
uniform float Specular: hint_range(0.0, 20.0) = 5.;
uniform float SpecularHardness = 300.;
uniform float Wetness: hint_range(0.0, 1.0) = 0.;

group_uniforms Rim_Light;
uniform float FresnelIOR = 2.;
uniform float FresnelPower = 8.;

void fragment() {
	vec3 normal = texture(Normal, UV).rgb;
	vec3 normalSkin = texture(SkinNormal, UV * SkinScale).rgb;
	NORMAL_MAP = mix(normal, normalSkin, SkinDepth);
	NORMAL_MAP_DEPTH = NormalDepth;

	// Diffuse
	vec3 color = texture(Diffuse, UV).rgb;
	vec3 hsv = rgb2hsv(color);
	// Optional: Desaturate image
	color = shiftHSV(color, 0., 1. - hsv.y * .3, 1.);
	float f = clamp(pow(remap(fresnel(EdgeHueFresnel, NORMAL, VIEW), 0.0, 1.0, -1.0, 1.0), EdgeHuePower), 0.0, 1.0);
	vec3 hueColor = shiftHSV(color, 0.5 + EdgeHue, 1.125, 1.0);
	ALBEDO = mix(color, hueColor, f);
}

void light()
{
	// Calculate some vectors.
	vec3 lightColor = LIGHT_COLOR / PI;
	vec3 L = normalize(LIGHT);
	vec3 N = normalize(NORMAL);

	// Diffuse light shadow (Lambert).
	float NdotL = dot(NORMAL, LIGHT) * ATTENUATION;
	float shadow = clamp(pow(NdotL + ShadowOffset, ShadowSoftness), ShadowAmount, 1.0);

	// Specular light
	vec3 V = normalize(VIEW);
	vec3 H = normalize(L + V);

	float specular = max(0.0, pow(dot(H, NORMAL), SpecularHardness)) * Specular;
	float specularSkin = texture(SkinSpecular, UV * SkinScale).r + specular * .03;
	
	// Change skin hue around lit areas
	float lightHue = pow(abs(shadow - .5) * 1.5, LightHuePower);
	vec3 alteredAlbedo = ALBEDO;
	alteredAlbedo = shiftHSV(alteredAlbedo, LightHueMult * lightHue, 1.0 + (.23 * lightHue), 1.0 + .23 * lightHue);
	
	float shadowHue = 1. - shadow;
	alteredAlbedo = mix(alteredAlbedo, shiftHSV(alteredAlbedo, -.1, 1.9, .5), shadowHue);
	
	float specularHue = pow(clamp(specular, 0., 1.), SpecularHuePower);
	alteredAlbedo = shiftHSV(alteredAlbedo, SpecularHueMult * specularHue, 1.0 + (0.6 * specularHue), 1.0);
	DIFFUSE_LIGHT += shadow * lightColor * alteredAlbedo;

	vec3 finalSpecular = (vec3(specular * specularSkin) * LIGHT_COLOR / PI) * max(0.0, 1.0 - pow(1.0 - NdotL, 20));
	SPECULAR_LIGHT += finalSpecular;
	
	// Subtle extra lit area
	SPECULAR_LIGHT += pow(specular, 0.05) * .125;
	
	// Wetness
	SPECULAR_LIGHT += specular * specularSkin * Wetness > .07 ? .3 : 0.001;
	
	// Rim light (fresnel)
	float mask = clamp(NdotL * 5.0, 0.0, 1.0);
	float rim = pow(fresnel(FresnelIOR, NORMAL, VIEW), FresnelPower);
	SPECULAR_LIGHT += clamp(rim, 0.0, 1.0) * mask;
}
Tags
Anime, character, skin, stylized
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from paper

Procedural Drops Animated – Rain / Sweat / etc

Related shaders

Anime Stylized Skin/Hairs/Clothes (4.3)

Absorption Based Stylized Water

Stylized Toon Water

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments