Created
April 19, 2026 06:26
-
-
Save jwosty/f65a83237d249c93374cdcf630d7b941 to your computer and use it in GitHub Desktop.
Simple toon shading lighting model used in Sheep, Inc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| float Quantize(float value, float n) { | |
| return n <= 0 ? value : floor((value*(n-1.0))+0.5)/(n-1.0); | |
| } | |
| float3 Quantize(float3 value, float n) { | |
| return float3(Quantize(value.x,n), Quantize(value.y,n), Quantize(value.z,n)); | |
| } | |
| /** | |
| * Lighting contribution of a single directional light source via Phong illumination. | |
| * | |
| * The vec3 returned is the RGB color of the light's contribution. | |
| * | |
| * k_a: Ambient color | |
| * k_d: Diffuse color | |
| * k_s: Specular color | |
| * alpha: Shininess coefficient | |
| * p: position of point being lit | |
| * V: vector from the point being lit to the camera (`normalize(eye - p)` for perspective proj, or `-cameraForward` for orthographic proj) | |
| * lightDir: the direction of the light | |
| * lightIntensity: color/intensity of the light | |
| * lightNormQuantization: a number representing the desired descrete levels to quantize the lighting into | |
| * | |
| * See https://en.wikipedia.org/wiki/Phong_reflection_model#Description | |
| */ | |
| #define phongContribForDirLight(/* float3 */ n, /* out float3 */ result, /* float3 */ k_d, /* float3 */ k_s, /* float */ alpha, /* float3 */ p, /* float3 */ V, /* float3 */ lightDir, /* float3 */ lightIntensity, /* float */ lightNormQuantization) { \ | |
| float3 N = n; \ | |
| float3 L = -lightDir; \ | |
| float3 R = normalize(reflect(-L, N)); \ | |
| /* Quantizing these vectors instead of output light values (or even colors later) gives a proper cel-shading effect */ \ | |
| float dotLN = Quantize(clamp(dot(L, N), 0.0, 1.0), lightNormQuantization); \ | |
| float dotRV = Quantize(dot(R, V), lightNormQuantization); \ | |
| if (dotLN < 0.0) { \ | |
| /* Light not visible from this point on the surface */ \ | |
| result = float3(0.0, 0.0, 0.0); \ | |
| } else if (dotRV < 0.0) { \ | |
| /* Light reflection in opposite direction as viewer, apply only diffuse component */ \ | |
| result = lightIntensity * (k_d * dotLN); \ | |
| } else { \ | |
| result = lightIntensity * (k_d * dotLN + k_s * pow(dotRV, alpha)); \ | |
| } \ | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment