[example] cel-shading and outline using inverted hull (#5615)

* added cel-shading and outline using inverted hull example

* new screenshot

* added glsl100+120 compat

* updated view

* unnecessary spacing
This commit is contained in:
Gleb A 2026-03-06 10:52:28 -05:00 • committed by GitHub
commit 54f630774d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 562 additions and 0 deletions

View file

@ -0,0 +1,60 @@
#version 330
in vec3 fragPosition;
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragNormal;
// Raylib standard uniforms
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// View position for future specular / fresnel use.
uniform vec3 viewPos;
// Number of discrete toon bands (2 = hard binary, 10 = default, 20 = near-smooth).
uniform float numBands;
// rlights.h compatible light block.
struct Light {
int enabled;
int type; // 0 = directional, 1 = point
vec3 position;
vec3 target;
vec4 color;
float attenuation;
};
uniform Light lights[4];
out vec4 finalColor;
void main() {
vec4 texColor = texture(texture0, fragTexCoord);
vec3 baseColor = texColor.rgb * fragColor.rgb * colDiffuse.rgb;
vec3 norm = normalize(fragNormal);
float lightAccum = 0.08; // ambient floor
for (int i = 0; i < 4; i++) {
if (lights[i].enabled == 0) continue;
vec3 lightDir;
if (lights[i].type == 0) {
// Directional: direction is from position toward target.
lightDir = normalize(lights[i].position - lights[i].target);
} else {
// Point: direction from surface to light.
lightDir = normalize(lights[i].position - fragPosition);
}
float NdotL = max(dot(norm, lightDir), 0.0);
// Quantize NdotL into numBands discrete steps.
// min() guards against NdotL == 1.0 producing an out-of-range index.
float quantized = min(floor(NdotL * numBands), numBands - 1.0) / (numBands - 1.0);
lightAccum += quantized * lights[i].color.r;
}
lightAccum = clamp(lightAccum, 0.0, 1.0);
finalColor = vec4(baseColor * lightAccum, texColor.a * colDiffuse.a);
}

View file

@ -0,0 +1,25 @@
#version 330
// Raylib standard attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Raylib standard uniforms
uniform mat4 mvp;
uniform mat4 matModel;
uniform mat4 matNormal;
out vec3 fragPosition;
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragNormal;
void main() {
fragPosition = vec3(matModel * vec4(vertexPosition, 1.0));
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragNormal = normalize(vec3(matNormal * vec4(vertexNormal, 0.0)));
gl_Position = mvp * vec4(vertexPosition, 1.0);
}

View file

@ -0,0 +1,7 @@
#version 330
out vec4 finalColor;
void main() {
finalColor = vec4(0.05, 0.05, 0.05, 1.0);
}

View file

@ -0,0 +1,15 @@
#version 330
in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 vertexTexCoord;
in vec4 vertexColor;
uniform mat4 mvp;
uniform float outlineThickness;
void main() {
// Extrude vertex along its normal to create the hull.
vec3 extruded = vertexPosition + vertexNormal * outlineThickness;
gl_Position = mvp * vec4(extruded, 1.0);
}