Matcap Shader
A very simple matcap shader, roughly based on the one uploaded by FireRabbit, but implementing a ‘fix’ demonstrated by Ben Cloward!
A matcap is an image of a ‘sphere’ or circle with details on it, which 3d models then use to determine their color and other information depending on what direction the model’s faces look on a screen-basis. Ie, a face looking to the upper left corner will sample from the upper-left part of this circle texture.
They’re great for quickly and cheaply adding consistent lighting information to an object, similar in vein to a Cubemap in that sense, although not 3d.
I’ve included examples of how to mix your normalmap into the shader within the code itself, as well as how to mix the matcap into your main material, though the base shader is as simple as it can be.
Shader code
// Special thanks to Ben Cloward for the amazing Material tutorial which improved this shader 20x!!
// Video here: https://www.youtube.com/watch?v=osgMB0mf23w
// Thanks to FireRabbit for the base which I pulled apart!
shader_type spatial;
render_mode unshaded; // remove this if you wish to make it shaded
uniform sampler2D matcap : source_color, hint_default_black; // Sampler 2d of the matcap
// Bread and buter: Generates the MatCap's UV's
vec2 generate_matcap_uv(vec3 _normal, vec3 _node_position_view) {
vec3 cross_space = cross(normalize(_node_position_view), _normal); // cross products the normal with it's base position
vec2 mat_space = vec2(cross_space.y * 1.0, cross_space.x); // converts to a Vec2 UV, having to switch x and y
mat_space *= vec2(-0.5, -0.5); // modifies the mat space's size to fit into uv coords, & flips it
mat_space += vec2(0.5, 0.5); // transforms the mat space into uv coords
return mat_space; // export the final uv's
}
void fragment(){
vec2 matcap_uv = (generate_matcap_uv(NORMAL, NODE_POSITION_VIEW)); // Matcap UV's
vec3 _matcap = texture(matcap, matcap_uv).rgb; // Matcap Texture
ALBEDO = _matcap; // Sets the albedo to the matcap texture.
}
//// Additional Information: \\\\\
// NOTE: this shader isn't perfect, sadly. There's still something causing some minor distortion on the material.
// I'll try to update this with the fix if it ever gets found.
// Feel free to improve upon this! Let me know if you do, too!
// If you want to make it make it take your normalmap into account, replace the [vec3 _matcap = ...] with:
//
// vec3 _matcap = texture(matcap, matcap_uv + ((texture([INSERT NORMALMAP], UV).xy - 0.5) * [INFLUENCE])).rgb;
//
// Replacing the [INSERT NORMALMAP] with your sampler2D normalmap
// and [INFLUENCE] with a float.
//
// The [.xy - 0.5] part maps the normal from vec3 [0 : 1] range into a vec2 [-0.5 : 0.5] range.
// You can correct it into a [-1 : 1] range by multiplying it by 2, but I found it's not really nessessary here.
// If you want to use a Metalness map or a Roughness map, or both, to influence the matcap:
// insert this to blend between the _matcap and a value like so:
//
// _matcap = mix(vec3(0.0), _matcap, clamp([metalness] + (1 - [roughness]), 0, 1);
//
// The example above is a super simple blend between the metal value, and the inverse rough value.
// Effectively meaning that the more metallic and more shiny the object, the more matcap it'll have
// You'll want to augment it and make it more complex than that though. It's just a quick example.
// If you want to add onto the default shading, you'll want to add the _matcap
// to your albedo or emissive layer instead of setting it like it is in this file. IE:
//
// ALBEDO = texture(albedo, UV)
// ALBEDO += _matcap
// EMISSION += _matcap
// Or multiply it if you want it to be more of a 'flashlight'/'shadow' kind of effect instead of a
// light.
// ALBEDO = texture(albedo, UV)
// ALBEDO *= _matcap
// or do both at the same time! Mix n Match! It's all up to you now :3
Great improvement
TY <3
Funnily enough: just a couple of hours ago, after days of further searching, I finally found (aka stole) a completely flawless solution! Zero artifacts, unlike this attempt which still has issues. Especially when the mesh is not at the origin point >.>
The source I lifted from is under a GNU GPL V2 License, so I’ll try to upload it in the morning (with credits, additional comments, and some minor adjustments. Much like this one.)
any updates on this? I’m currently working on a project that could really use a flawless matcap