Skip to content

Commit fe0cdc2

Browse files
maiconpintoabreupsxdev
authored andcommitted
Add ascii post processing (raysan5#5213)
1 parent 86004e2 commit fe0cdc2

5 files changed

Lines changed: 317 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#version 100
2+
3+
precision mediump float;
4+
5+
// Input from the vertex shader
6+
varying vec2 fragTexCoord;
7+
8+
// Output color for the screen
9+
varying vec4 finalColor;
10+
11+
uniform sampler2D texture0;
12+
uniform vec2 resolution;
13+
uniform float fontSize;
14+
15+
float greyScale(in vec3 col) {
16+
return dot(col, vec3(0.2126, 0.7152, 0.0722));
17+
}
18+
19+
float character(float n, vec2 p)
20+
{
21+
p = floor(p * vec2(4.0, -4.0) + 2.5);
22+
23+
// Check if the coordinate is inside the 5x5 grid (0 to 4).
24+
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y) {
25+
26+
if (int(mod(n / exp2(p.x + 5.0 * p.y), 2.0)) == 1) {
27+
return 1.0; // The bit is on, so draw this part of the character.
28+
}
29+
}
30+
31+
return 0.0; // The bit is off, or we are outside the grid.
32+
}
33+
34+
// -----------------------------------------------------------------------------
35+
// Main shader logic
36+
// -----------------------------------------------------------------------------
37+
void main()
38+
{
39+
vec2 charPixelSize = vec2(fontSize, fontSize * 1.8);
40+
vec2 uvCellSize = charPixelSize / resolution;
41+
42+
vec2 cellUV = floor(fragTexCoord / uvCellSize) * uvCellSize;
43+
44+
vec3 cellColor = texture2D(texture0, cellUV).rgb;
45+
float gray = greyScale(cellColor);
46+
47+
float n = 4096;
48+
49+
// limited character set
50+
if (gray > 0.2) n = 65600.0; // :
51+
if (gray > 0.3) n = 163153.0; // *
52+
if (gray > 0.4) n = 15255086.0; // o
53+
if (gray > 0.5) n = 13121101.0; // &
54+
if (gray > 0.6) n = 15252014.0; // 8
55+
if (gray > 0.7) n = 13195790.0; // @
56+
if (gray > 0.8) n = 11512810.0; // #
57+
58+
vec2 localUV = (fragTexCoord - cellUV) / uvCellSize; // Range [0.0, 1.0]
59+
60+
vec2 p = localUV * 2.0 - 1.0;
61+
62+
float charShape = character(n, p);
63+
64+
vec3 final_col = cellColor * charShape;
65+
66+
gl_FragColor = vec4(final_col, 1.0);
67+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#version 120
2+
3+
// Input from the vertex shader
4+
varying vec2 fragTexCoord;
5+
6+
// Output color for the screen
7+
varying vec4 finalColor;
8+
9+
uniform sampler2D texture0;
10+
uniform vec2 resolution;
11+
uniform float fontSize;
12+
13+
float greyScale(in vec3 col) {
14+
return dot(col, vec3(0.2126, 0.7152, 0.0722));
15+
}
16+
17+
float character(float n, vec2 p)
18+
{
19+
p = floor(p * vec2(4.0, -4.0) + 2.5);
20+
21+
// Check if the coordinate is inside the 5x5 grid (0 to 4).
22+
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y) {
23+
24+
if (int(mod(n / exp2(p.x + 5.0 * p.y), 2.0)) == 1) {
25+
return 1.0; // The bit is on, so draw this part of the character.
26+
}
27+
}
28+
29+
return 0.0; // The bit is off, or we are outside the grid.
30+
}
31+
32+
// -----------------------------------------------------------------------------
33+
// Main shader logic
34+
// -----------------------------------------------------------------------------
35+
void main()
36+
{
37+
vec2 charPixelSize = vec2(fontSize, fontSize * 1.8);
38+
vec2 uvCellSize = charPixelSize / resolution;
39+
40+
vec2 cellUV = floor(fragTexCoord / uvCellSize) * uvCellSize;
41+
42+
vec3 cellColor = texture2D(texture0, cellUV).rgb;
43+
float gray = greyScale(cellColor);
44+
45+
float n = 4096;
46+
47+
// limited character set
48+
if (gray > 0.2) n = 65600.0; // :
49+
if (gray > 0.3) n = 163153.0; // *
50+
if (gray > 0.4) n = 15255086.0; // o
51+
if (gray > 0.5) n = 13121101.0; // &
52+
if (gray > 0.6) n = 15252014.0; // 8
53+
if (gray > 0.7) n = 13195790.0; // @
54+
if (gray > 0.8) n = 11512810.0; // #
55+
56+
vec2 localUV = (fragTexCoord - cellUV) / uvCellSize; // Range [0.0, 1.0]
57+
58+
vec2 p = localUV * 2.0 - 1.0;
59+
60+
float charShape = character(n, p);
61+
62+
vec3 final_col = cellColor * charShape;
63+
64+
gl_FragColor = vec4(final_col, 1.0);
65+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#version 330
2+
3+
// Input from the vertex shader
4+
in vec2 fragTexCoord;
5+
6+
// Output color for the screen
7+
out vec4 finalColor;
8+
9+
uniform sampler2D texture0;
10+
uniform vec2 resolution;
11+
uniform float fontSize;
12+
13+
float greyScale(in vec3 col) {
14+
return dot(col, vec3(0.2126, 0.7152, 0.0722));
15+
}
16+
17+
float character(float n, vec2 p)
18+
{
19+
p = floor(p * vec2(4.0, -4.0) + 2.5);
20+
21+
// Check if the coordinate is inside the 5x5 grid (0 to 4).
22+
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y) {
23+
24+
if (int(mod(n / exp2(p.x + 5.0 * p.y), 2.0)) == 1) {
25+
return 1.0; // The bit is on, so draw this part of the character.
26+
}
27+
}
28+
29+
return 0.0; // The bit is off, or we are outside the grid.
30+
}
31+
32+
// -----------------------------------------------------------------------------
33+
// Main shader logic
34+
// -----------------------------------------------------------------------------
35+
36+
void main()
37+
{
38+
vec2 charPixelSize = vec2(fontSize, fontSize * 1.8);
39+
vec2 uvCellSize = charPixelSize / resolution;
40+
41+
vec2 cellUV = floor(fragTexCoord / uvCellSize) * uvCellSize;
42+
43+
vec3 cellColor = texture(texture0, cellUV).rgb;
44+
float gray = greyScale(cellColor);
45+
46+
float n = 4096;
47+
48+
// limited character set
49+
if (gray > 0.2) n = 65600.0; // :
50+
if (gray > 0.3) n = 163153.0; // *
51+
if (gray > 0.4) n = 15255086.0; // o
52+
if (gray > 0.5) n = 13121101.0; // &
53+
if (gray > 0.6) n = 15252014.0; // 8
54+
if (gray > 0.7) n = 13195790.0; // @
55+
if (gray > 0.8) n = 11512810.0; // #
56+
57+
vec2 localUV = (fragTexCoord - cellUV) / uvCellSize; // Range [0.0, 1.0]
58+
59+
vec2 p = localUV * 2.0 - 1.0;
60+
61+
float charShape = character(n, p);
62+
63+
vec3 final_col = cellColor * charShape;
64+
65+
finalColor = vec4(final_col, 1.0);
66+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*******************************************************************************************
2+
*
3+
* raylib [shaders] example - ascii effect
4+
*
5+
* Example complexity rating: [★☆☆☆] 1/4
6+
*
7+
* Example originally created with raylib 5.5, last time updated with raylib 5.6
8+
*
9+
* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5)
10+
*
11+
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
12+
* BSD-like license that allows static linking with closed source software
13+
*
14+
* Copyright (c) 2025-2025 Maicon Santana (@maiconpintoabreu)
15+
*
16+
********************************************************************************************/
17+
18+
#include "raylib.h"
19+
20+
#if defined(PLATFORM_DESKTOP)
21+
#define GLSL_VERSION 330
22+
#else // PLATFORM_ANDROID, PLATFORM_WEB
23+
#define GLSL_VERSION 100
24+
#endif
25+
26+
//------------------------------------------------------------------------------------
27+
// Program main entry point
28+
//------------------------------------------------------------------------------------
29+
int main(void)
30+
{
31+
// Initialization
32+
//--------------------------------------------------------------------------------------
33+
const int screenWidth = 800;
34+
const int screenHeight = 450;
35+
36+
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - ascii effect");
37+
38+
// Texture to test static drawing
39+
Texture2D fudesumi = LoadTexture("resources/fudesumi.png");
40+
// Texture to test moving drawing
41+
Texture2D raysan = LoadTexture("resources/raysan.png");
42+
43+
// Load shader to be used on postprocessing
44+
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/ascii.fs", GLSL_VERSION));
45+
46+
// These locations are used to send data to the GPU.
47+
int resolutionLoc = GetShaderLocation(shader, "resolution");
48+
int fontSizeLoc = GetShaderLocation(shader, "fontSize");
49+
50+
// Set the character size for the ASCII effect
51+
float fontSize = 4.0f;
52+
53+
// Send the updated values to the shader
54+
float resolution[2] = { (float)screenWidth, (float)screenHeight };
55+
SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
56+
SetShaderValue(shader, fontSizeLoc, &fontSize, SHADER_UNIFORM_FLOAT);
57+
58+
Vector2 circlePos = (Vector2){40.0f, (float)screenHeight * 0.5f};
59+
float circleSpeed = 1.0f;
60+
61+
// RenderTexture to apply the postprocessing later
62+
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
63+
64+
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
65+
//--------------------------------------------------------------------------------------
66+
67+
// Main game loop
68+
while (!WindowShouldClose()) // Detect window close button or ESC key
69+
{
70+
// Update
71+
//----------------------------------------------------------------------------------
72+
if (circlePos.x > 200.0f || circlePos.x < 40.0f) {
73+
circleSpeed *= -1;
74+
}
75+
circlePos.x += circleSpeed;
76+
77+
// Draw
78+
//----------------------------------------------------------------------------------
79+
80+
BeginTextureMode(target);
81+
ClearBackground(WHITE); // The background of the scene itself
82+
83+
DrawTexture(fudesumi, 500, -30, WHITE); // Using custom shader
84+
DrawTextureV(raysan, circlePos, WHITE);
85+
86+
EndTextureMode();
87+
BeginDrawing();
88+
89+
ClearBackground(RAYWHITE);
90+
91+
BeginShaderMode(shader);
92+
93+
// Draw the scene texture (that we rendered earlier) to the screen.
94+
// The shader will process every pixel of this texture.
95+
DrawTextureRec(target.texture,
96+
(Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height },
97+
(Vector2){ 0, 0 },
98+
WHITE);
99+
EndShaderMode();
100+
101+
DrawRectangle(0, 0, screenWidth, 40, BLACK);
102+
DrawText("Ascii effect", 120, 10, 20, LIGHTGRAY);
103+
DrawFPS(10, 10);
104+
105+
EndDrawing();
106+
//----------------------------------------------------------------------------------
107+
}
108+
109+
// De-Initialization
110+
//--------------------------------------------------------------------------------------
111+
UnloadShader(shader); // Unload shader
112+
UnloadTexture(fudesumi); // Unload texture
113+
UnloadTexture(raysan); // Unload texture
114+
115+
CloseWindow(); // Close window and OpenGL context
116+
//--------------------------------------------------------------------------------------
117+
118+
return 0;
119+
}
44.1 KB
Loading

0 commit comments

Comments
 (0)