From 54f630774d62699dfdd79d2a9f4eba9269f38aa4 Mon Sep 17 00:00:00 2001 From: Gleb A Date: Fri, 6 Mar 2026 10:52:28 -0500 Subject: [PATCH] [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 --- .../shaders/resources/shaders/glsl100/cel.fs | 58 +++++ .../shaders/resources/shaders/glsl100/cel.vs | 47 ++++ .../resources/shaders/glsl100/outline_hull.fs | 8 + .../resources/shaders/glsl100/outline_hull.vs | 15 ++ .../shaders/resources/shaders/glsl120/cel.fs | 56 +++++ .../shaders/resources/shaders/glsl120/cel.vs | 48 +++++ .../resources/shaders/glsl120/outline_hull.fs | 6 + .../resources/shaders/glsl120/outline_hull.vs | 15 ++ .../shaders/resources/shaders/glsl330/cel.fs | 60 ++++++ .../shaders/resources/shaders/glsl330/cel.vs | 25 +++ .../resources/shaders/glsl330/outline_hull.fs | 7 + .../resources/shaders/glsl330/outline_hull.vs | 15 ++ examples/shaders/shaders_cel_shading.c | 202 ++++++++++++++++++ examples/shaders/shaders_cel_shading.png | Bin 0 -> 45710 bytes 14 files changed, 562 insertions(+) create mode 100644 examples/shaders/resources/shaders/glsl100/cel.fs create mode 100644 examples/shaders/resources/shaders/glsl100/cel.vs create mode 100644 examples/shaders/resources/shaders/glsl100/outline_hull.fs create mode 100644 examples/shaders/resources/shaders/glsl100/outline_hull.vs create mode 100644 examples/shaders/resources/shaders/glsl120/cel.fs create mode 100644 examples/shaders/resources/shaders/glsl120/cel.vs create mode 100644 examples/shaders/resources/shaders/glsl120/outline_hull.fs create mode 100644 examples/shaders/resources/shaders/glsl120/outline_hull.vs create mode 100644 examples/shaders/resources/shaders/glsl330/cel.fs create mode 100644 examples/shaders/resources/shaders/glsl330/cel.vs create mode 100644 examples/shaders/resources/shaders/glsl330/outline_hull.fs create mode 100644 examples/shaders/resources/shaders/glsl330/outline_hull.vs create mode 100644 examples/shaders/shaders_cel_shading.c create mode 100644 examples/shaders/shaders_cel_shading.png diff --git a/examples/shaders/resources/shaders/glsl100/cel.fs b/examples/shaders/resources/shaders/glsl100/cel.fs new file mode 100644 index 000000000..dfc22d0c0 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/cel.fs @@ -0,0 +1,58 @@ +#version 100 + +precision mediump float; + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform vec3 viewPos; +uniform float numBands; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; +uniform Light lights[4]; + +void main() +{ + vec4 texColor = texture2D(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 == 1) // no continue in GLSL ES 1.0 + { + 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. + 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); + gl_FragColor = vec4(baseColor * lightAccum, texColor.a * colDiffuse.a); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/cel.vs b/examples/shaders/resources/shaders/glsl100/cel.vs new file mode 100644 index 000000000..153842a9b --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/cel.vs @@ -0,0 +1,47 @@ +#version 100 + +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +uniform mat4 mvp; +uniform mat4 matModel; + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +mat3 inverse(mat3 m) +{ + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + float b01 = a22*a11 - a12*a21; + float b11 = -a22*a10 + a12*a20; + float b21 = a21*a10 - a11*a20; + float det = a00*b01 + a01*b11 + a02*b21; + return mat3(b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11), + b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10), + b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) / det; +} + +mat3 transpose(mat3 m) +{ + return mat3(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +void main() +{ + fragPosition = vec3(matModel * vec4(vertexPosition, 1.0)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix * vertexNormal); + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/outline_hull.fs b/examples/shaders/resources/shaders/glsl100/outline_hull.fs new file mode 100644 index 000000000..4f82cfc87 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/outline_hull.fs @@ -0,0 +1,8 @@ +#version 100 + +precision mediump float; + +void main() +{ + gl_FragColor = vec4(0.05, 0.05, 0.05, 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl100/outline_hull.vs b/examples/shaders/resources/shaders/glsl100/outline_hull.vs new file mode 100644 index 000000000..af7be8831 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/outline_hull.vs @@ -0,0 +1,15 @@ +#version 100 + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +attribute vec2 vertexTexCoord; +attribute vec4 vertexColor; + +uniform mat4 mvp; +uniform float outlineThickness; + +void main() +{ + vec3 extruded = vertexPosition + vertexNormal * outlineThickness; + gl_Position = mvp * vec4(extruded, 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl120/cel.fs b/examples/shaders/resources/shaders/glsl120/cel.fs new file mode 100644 index 000000000..88321e60f --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/cel.fs @@ -0,0 +1,56 @@ +#version 120 + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform vec3 viewPos; +uniform float numBands; + +struct Light { + int enabled; + int type; + vec3 position; + vec3 target; + vec4 color; +}; +uniform Light lights[4]; + +void main() +{ + vec4 texColor = texture2D(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 == 1) + { + 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. + 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); + gl_FragColor = vec4(baseColor * lightAccum, texColor.a * colDiffuse.a); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl120/cel.vs b/examples/shaders/resources/shaders/glsl120/cel.vs new file mode 100644 index 000000000..3c736aec7 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/cel.vs @@ -0,0 +1,48 @@ +#version 120 + +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec3 vertexNormal; +attribute vec4 vertexColor; + +uniform mat4 mvp; +uniform mat4 matModel; + +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; + +// inverse() and transpose() are not built-in until GLSL 1.40 +mat3 inverse(mat3 m) +{ + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + float b01 = a22*a11 - a12*a21; + float b11 = -a22*a10 + a12*a20; + float b21 = a21*a10 - a11*a20; + float det = a00*b01 + a01*b11 + a02*b21; + return mat3(b01, (-a22*a01 + a02*a21), ( a12*a01 - a02*a11), + b11, ( a22*a00 - a02*a20), (-a12*a00 + a02*a10), + b21, (-a21*a00 + a01*a20), ( a11*a00 - a01*a10)) / det; +} + +mat3 transpose(mat3 m) +{ + return mat3(m[0][0], m[1][0], m[2][0], + m[0][1], m[1][1], m[2][1], + m[0][2], m[1][2], m[2][2]); +} + +void main() +{ + fragPosition = vec3(matModel * vec4(vertexPosition, 1.0)); + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + mat3 normalMatrix = transpose(inverse(mat3(matModel))); + fragNormal = normalize(normalMatrix * vertexNormal); + + gl_Position = mvp * vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl120/outline_hull.fs b/examples/shaders/resources/shaders/glsl120/outline_hull.fs new file mode 100644 index 000000000..b6e4fc828 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/outline_hull.fs @@ -0,0 +1,6 @@ +#version 120 + +void main() +{ + gl_FragColor = vec4(0.05, 0.05, 0.05, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl120/outline_hull.vs b/examples/shaders/resources/shaders/glsl120/outline_hull.vs new file mode 100644 index 000000000..7ad125be1 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/outline_hull.vs @@ -0,0 +1,15 @@ +#version 120 + +attribute vec3 vertexPosition; +attribute vec3 vertexNormal; +attribute vec2 vertexTexCoord; +attribute vec4 vertexColor; + +uniform mat4 mvp; +uniform float outlineThickness; + +void main() +{ + vec3 extruded = vertexPosition + vertexNormal * outlineThickness; + gl_Position = mvp * vec4(extruded, 1.0); +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/cel.fs b/examples/shaders/resources/shaders/glsl330/cel.fs new file mode 100644 index 000000000..78a2097c2 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/cel.fs @@ -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); +} diff --git a/examples/shaders/resources/shaders/glsl330/cel.vs b/examples/shaders/resources/shaders/glsl330/cel.vs new file mode 100644 index 000000000..37a8d200d --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/cel.vs @@ -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); +} diff --git a/examples/shaders/resources/shaders/glsl330/outline_hull.fs b/examples/shaders/resources/shaders/glsl330/outline_hull.fs new file mode 100644 index 000000000..c8a33de08 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/outline_hull.fs @@ -0,0 +1,7 @@ +#version 330 + +out vec4 finalColor; + +void main() { + finalColor = vec4(0.05, 0.05, 0.05, 1.0); +} diff --git a/examples/shaders/resources/shaders/glsl330/outline_hull.vs b/examples/shaders/resources/shaders/glsl330/outline_hull.vs new file mode 100644 index 000000000..2e350201e --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/outline_hull.vs @@ -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); +} diff --git a/examples/shaders/shaders_cel_shading.c b/examples/shaders/shaders_cel_shading.c new file mode 100644 index 000000000..cab86a26f --- /dev/null +++ b/examples/shaders/shaders_cel_shading.c @@ -0,0 +1,202 @@ +/******************************************************************************************* +* +* raylib [shaders] example - cel shading +* +* Example complexity rating: [★★★☆] 3/4 +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3) +* +* Example contributed by Gleb A (@ggrizzly) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2015-2026 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" +#include "rlgl.h" +#include +#include + +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +//------------------------------------------------------------------------------------ +// Model table: path, optional diffuse texture path (NULL = embedded), draw scale +//------------------------------------------------------------------------------------ +typedef struct { + const char *modelPath; + const char *texturePath; // NULL for GLB files with embedded textures + float scale; + float outlineThickness; +} ModelInfo; + +static const ModelInfo MODEL = { "resources/models/old_car_new.glb", NULL, 0.75f, 0.005f }; + + +//------------------------------------------------------------------------------------ +// Load model and its diffuse texture (if any). Does NOT assign a shader. +//------------------------------------------------------------------------------------ +static Model celLoadModel() +{ + Model model = LoadModel(MODEL.modelPath); + + if (MODEL.texturePath != NULL) + { + Texture2D tex = LoadTexture(MODEL.texturePath); + model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = tex; + } + + return model; +} + +static void ApplyShaderToModel(Model model, Shader shader) +{ + model.materials[0].shader = shader; +} + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - cel shading"); + + Camera camera = { 0 }; + camera.position = (Vector3){ 9.0f, 6.0f, 9.0f }; + camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 45.0f; + camera.projection = CAMERA_PERSPECTIVE; + + // Load cel shader + Shader celShader = LoadShader(TextFormat("resources/shaders/glsl%i/cel.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/cel.fs", GLSL_VERSION)); + celShader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(celShader, "viewPos"); + + // numBands: controls toon quantization steps (2 = hard binary, 20 = near-smooth) + float numBands = 10.0f; + int numBandsLoc = GetShaderLocation(celShader, "numBands"); + SetShaderValue(celShader, numBandsLoc, &numBands, SHADER_UNIFORM_FLOAT); + + // Inverted-hull outline shader: draws back faces extruded along normals + Shader outlineShader = LoadShader( + TextFormat("resources/shaders/glsl%i/outline_hull.vs", GLSL_VERSION), + TextFormat("resources/shaders/glsl%i/outline_hull.fs", GLSL_VERSION)); + int outlineThicknessLoc = GetShaderLocation(outlineShader, "outlineThickness"); + + // Single directional white light, angled so toon bands are visible on the model sides. + // Spins opposite to CAMERA_ORBITAL (0.5 rad/s) so lighting changes as you watch. + Light lights[MAX_LIGHTS] = { 0 }; + lights[0] = CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 50.0f, 50.0f, 50.0f }, Vector3Zero(), WHITE, celShader); + + + bool celEnabled = true; + bool outlineEnabled = true; + + Model model = celLoadModel(); + Shader defaultShader = model.materials[0].shader; + ApplyShaderToModel(model, celShader); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera, CAMERA_ORBITAL); + + float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; + SetShaderValue(celShader, celShader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3); + + // [Z] Toggle cel shading on/off + if (IsKeyPressed(KEY_Z)) + { + celEnabled = !celEnabled; + ApplyShaderToModel(model, celEnabled ? celShader : defaultShader); + } + + // [C] Toggle outline on/off + if (IsKeyPressed(KEY_C)) outlineEnabled = !outlineEnabled; + + // [Q/E] Decrease/increase toon band count (press or hold to repeat) + if (IsKeyPressed(KEY_E) || IsKeyPressedRepeat(KEY_E)) numBands = Clamp(numBands + 1.0f, 2.0f, 20.0f); + if (IsKeyPressed(KEY_Q) || IsKeyPressedRepeat(KEY_Q)) numBands = Clamp(numBands - 1.0f, 2.0f, 20.0f); + SetShaderValue(celShader, numBandsLoc, &numBands, SHADER_UNIFORM_FLOAT); + + // Spin light opposite to CAMERA_ORBITAL (0.5 rad/s), angled 45 degrees off vertical + float t = (float)GetTime(); + lights[0].position = (Vector3){ + sinf(-t * 0.3f) * 5.0f, + 5.0f, + cosf(-t * 0.3f) * 5.0f + }; + + for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(celShader, lights[i]); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + if (outlineEnabled) + { + // Outline pass: cull front faces, draw extruded back faces as silhouette + float thickness = MODEL.outlineThickness; + SetShaderValue(outlineShader, outlineThicknessLoc, &thickness, SHADER_UNIFORM_FLOAT); + rlSetCullFace(RL_CULL_FACE_FRONT); + ApplyShaderToModel(model, outlineShader); + DrawModel(model, Vector3Zero(), MODEL.scale, WHITE); + ApplyShaderToModel(model, celEnabled ? celShader : defaultShader); + rlSetCullFace(RL_CULL_FACE_BACK); + } + + DrawModel(model, Vector3Zero(), MODEL.scale, WHITE); + DrawSphereEx(lights[0].position, 0.2f, 50, 50, YELLOW); // Light position indicator + DrawGrid(10, 10.0f); + + EndMode3D(); + + DrawFPS(10, 10); + DrawText(TextFormat("Cel: %s [Z]", celEnabled ? "ON" : "OFF"), 10, 65, 20, celEnabled ? DARKGREEN : DARKGRAY); + DrawText(TextFormat("Outline: %s [C]", outlineEnabled ? "ON" : "OFF"), 10, 90, 20, outlineEnabled ? DARKGREEN : DARKGRAY); + DrawText(TextFormat("Bands: %.0f [Q/E]", numBands), 10, 115, 20, DARKGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model); + UnloadShader(celShader); + UnloadShader(outlineShader); + CloseWindow(); + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_cel_shading.png b/examples/shaders/shaders_cel_shading.png new file mode 100644 index 0000000000000000000000000000000000000000..51b98225e093acc13d235192e2213a3c760da4a1 GIT binary patch literal 45710 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 GgeCw`#8Q?3 literal 0 HcmV?d00001