Browse Source

[examples] Fix `shaders_ascii_rendering` (#5219)

* Add ascii post processing

* Fix broken characters and add more comments

* Rename example

* Refactored as requested
Maicon Santana 2 months ago
parent
commit
a553fbd0c7

+ 36 - 23
examples/shaders/resources/shaders/glsl100/ascii.fs

@@ -10,58 +10,71 @@ varying vec4 finalColor;
 
 uniform sampler2D texture0;
 uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
 uniform float fontSize;
 
-float greyScale(in vec3 col) {
+float GreyScale(in vec3 col)
+{
     return dot(col, vec3(0.2126, 0.7152, 0.0722));
 }
 
-float character(float n, vec2 p)
+float GetCharacter(float n, vec2 p)
 {
-	p = floor(p * vec2(4.0, -4.0) + 2.5);
-	
-	// Check if the coordinate is inside the 5x5 grid (0 to 4).
-	if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y) {
-        
-		if (int(mod(n / exp2(p.x + 5.0 * p.y), 2.0)) == 1) {
-            return 1.0; // The bit is on, so draw this part of the character.
+    p = floor(p*vec2(-4.0, 4.0) + 2.5);
+
+    // Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
+    if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
+    {
+        float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
+
+        // This checked if the 'a'-th bit of 'n' was set
+        float shiftedN = floor(n/pow(2.0, a));
+
+        if (mod(shiftedN, 2.0) == 1.0)
+        {
+            return 1.0; // The bit is on
         }
     }
 
-	return 0.0; // The bit is off, or we are outside the grid.
+    return 0.0; // The bit is off, or we are outside the grid
 }
 
 // -----------------------------------------------------------------------------
 // Main shader logic
 // -----------------------------------------------------------------------------
+
 void main() 
 {
-    vec2 charPixelSize = vec2(fontSize, fontSize * 1.8);
-    vec2 uvCellSize = charPixelSize / resolution;
+    vec2 charPixelSize = vec2(fontSize, fontSize);
+    vec2 uvCellSize = charPixelSize/resolution;
 
-    vec2 cellUV = floor(fragTexCoord / uvCellSize) * uvCellSize;
+    // The cell size is based on the fontSize set by application
+    vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
 
     vec3 cellColor = texture2D(texture0, cellUV).rgb;
-    float gray = greyScale(cellColor);
 
-	float n =  4096;
+    // Gray is used to define what character will be selected to draw
+    float gray = GreyScale(cellColor);
+
+	float n =  4096.0;
     
-    // limited character set
+    // Character set from https://www.shadertoy.com/view/lssGDj
+    // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
     if (gray > 0.2) n = 65600.0;    // :
-	if (gray > 0.3) n = 163153.0;   // *
+	if (gray > 0.3) n = 18725316.0; // v
 	if (gray > 0.4) n = 15255086.0; // o 
 	if (gray > 0.5) n = 13121101.0; // &
 	if (gray > 0.6) n = 15252014.0; // 8
 	if (gray > 0.7) n = 13195790.0; // @
 	if (gray > 0.8) n = 11512810.0; // #
 
-    vec2 localUV = (fragTexCoord - cellUV) / uvCellSize; // Range [0.0, 1.0]
-
-    vec2 p = localUV * 2.0 - 1.0;
+    vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
 
-    float charShape = character(n, p);
+    vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
 
-    vec3 final_col = cellColor * charShape;
+    // cellColor and charShape will define the color of the char
+    vec3 color = cellColor*GetCharacter(n, p);
 
-    gl_FragColor = vec4(final_col, 1.0);
+    gl_FragColor = vec4(color, 1.0);
 }

+ 35 - 22
examples/shaders/resources/shaders/glsl120/ascii.fs

@@ -8,58 +8,71 @@ varying vec4 finalColor;
 
 uniform sampler2D texture0;
 uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
 uniform float fontSize;
 
-float greyScale(in vec3 col) {
+float GreyScale(in vec3 col)
+{
     return dot(col, vec3(0.2126, 0.7152, 0.0722));
 }
 
-float character(float n, vec2 p)
+float GetCharacter(float n, vec2 p)
 {
-	p = floor(p * vec2(4.0, -4.0) + 2.5);
-	
-	// Check if the coordinate is inside the 5x5 grid (0 to 4).
-	if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y) {
-        
-		if (int(mod(n / exp2(p.x + 5.0 * p.y), 2.0)) == 1) {
-            return 1.0; // The bit is on, so draw this part of the character.
+    p = floor(p*vec2(-4.0, 4.0) + 2.5);
+
+    // Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
+    if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
+    {
+        float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
+
+        // This checked if the 'a'-th bit of 'n' was set
+        float shiftedN = floor(n/pow(2.0, a));
+
+        if (mod(shiftedN, 2.0) == 1.0)
+        {
+            return 1.0; // The bit is on
         }
     }
 
-	return 0.0; // The bit is off, or we are outside the grid.
+    return 0.0; // The bit is off, or we are outside the grid
 }
 
 // -----------------------------------------------------------------------------
 // Main shader logic
 // -----------------------------------------------------------------------------
+
 void main() 
 {
-    vec2 charPixelSize = vec2(fontSize, fontSize * 1.8);
+    vec2 charPixelSize = vec2(fontSize, fontSize);
     vec2 uvCellSize = charPixelSize / resolution;
 
-    vec2 cellUV = floor(fragTexCoord / uvCellSize) * uvCellSize;
+    // The cell size is based on the fontSize set by application
+    vec2 cellUV = floor(fragTexCoord / uvCellSize)*uvCellSize;
 
     vec3 cellColor = texture2D(texture0, cellUV).rgb;
-    float gray = greyScale(cellColor);
 
-	float n =  4096;
+    // Gray is used to define what character will be selected to draw
+    float gray = GreyScale(cellColor);
+
+	float n =  4096.0;
     
-    // limited character set
+    // Character set from https://www.shadertoy.com/view/lssGDj
+    // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
     if (gray > 0.2) n = 65600.0;    // :
-	if (gray > 0.3) n = 163153.0;   // *
+	if (gray > 0.3) n = 18725316.0; // v
 	if (gray > 0.4) n = 15255086.0; // o 
 	if (gray > 0.5) n = 13121101.0; // &
 	if (gray > 0.6) n = 15252014.0; // 8
 	if (gray > 0.7) n = 13195790.0; // @
 	if (gray > 0.8) n = 11512810.0; // #
 
-    vec2 localUV = (fragTexCoord - cellUV) / uvCellSize; // Range [0.0, 1.0]
-
-    vec2 p = localUV * 2.0 - 1.0;
+    vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
 
-    float charShape = character(n, p);
+    vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
 
-    vec3 final_col = cellColor * charShape;
+    // cellColor and charShape will define the color of the char
+    vec3 color = cellColor*GetCharacter(n, p);
 
-    gl_FragColor = vec4(final_col, 1.0);
+    gl_FragColor = vec4(color, 1.0);
 }

+ 27 - 17
examples/shaders/resources/shaders/glsl330/ascii.fs

@@ -8,6 +8,8 @@ out vec4 finalColor;
 
 uniform sampler2D texture0;
 uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
 uniform float fontSize;
 
 float GreyScale(in vec3 col)
@@ -15,16 +17,17 @@ float GreyScale(in vec3 col)
     return dot(col, vec3(0.2126, 0.7152, 0.0722));
 }
 
-float GetCharacter(float n, vec2 p)
+float GetCharacter(int n, vec2 p)
 {
-	p = floor(p*vec2(4.0, -4.0) + 2.5);
+	p = floor(p*vec2(-4.0, 4.0) + 2.5);
 	
 	// Check if the coordinate is inside the 5x5 grid (0 to 4)
 	if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
     {
-		if (int(mod(n/exp2(p.x + 5.0 * p.y), 2.0)) == 1)
+        int a = int(round(p.x) + 5.0*round(p.y));
+        if (((n >> a) & 1) == 1)
         {
-            return 1.0; // The bit is on, so draw this part of the character
+            return 1.0;
         }
     }
 
@@ -34,30 +37,37 @@ float GetCharacter(float n, vec2 p)
 // -----------------------------------------------------------------------------
 // Main shader logic
 // -----------------------------------------------------------------------------
+
 void main() 
 {
-    vec2 charPixelSize = vec2(fontSize, fontSize*1.8);
+    vec2 charPixelSize = vec2(fontSize, fontSize);
     vec2 uvCellSize = charPixelSize/resolution;
+
+    // The cell size is based on the fontSize set by application
     vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
 
     vec3 cellColor = texture(texture0, cellUV).rgb;
+
+    // Gray is used to define what character will be selected to draw
     float gray = GreyScale(cellColor);
 
-	float n =  4096;
+	int n =  4096;
     
-    // Limited character set
-    if (gray > 0.2) n = 65600.0;    // :
-	if (gray > 0.3) n = 163153.0;   // *
-	if (gray > 0.4) n = 15255086.0; // o 
-	if (gray > 0.5) n = 13121101.0; // &
-	if (gray > 0.6) n = 15252014.0; // 8
-	if (gray > 0.7) n = 13195790.0; // @
-	if (gray > 0.8) n = 11512810.0; // #
+    // Character set from https://www.shadertoy.com/view/lssGDj
+    // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
+    if (gray > 0.2) n = 65600;    // :
+	if (gray > 0.3) n = 18725316; // v
+	if (gray > 0.4) n = 15255086; // o 
+	if (gray > 0.5) n = 13121101; // &
+	if (gray > 0.6) n = 15252014; // 8
+	if (gray > 0.7) n = 13195790; // @
+	if (gray > 0.8) n = 11512810; // #
 
     vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
-    vec2 p = localUV*2.0 - 1.0;
 
-    float charShape = GetCharacter(n, p);
+    vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
+
+    vec3 color = cellColor*GetCharacter(n, p);
 
-    finalColor = vec4(cellColor*charShape, 1.0);
+    finalColor = vec4(color, 1.0);
 }

+ 27 - 17
examples/shaders/shaders_ascii_rendering.c

@@ -48,14 +48,14 @@ int main(void)
     int fontSizeLoc = GetShaderLocation(shader, "fontSize");
 
     // Set the character size for the ASCII effect
-    float fontSize = 4.0f;
+    // Fontsize should be 9 or more
+    float fontSize = 9.0f;
 
     // Send the updated values to the shader
     float resolution[2] = { (float)screenWidth, (float)screenHeight };
     SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
-    SetShaderValue(shader, fontSizeLoc, &fontSize, SHADER_UNIFORM_FLOAT);
 
-    Vector2 circlePos = (Vector2){40.0f, (float)screenHeight * 0.5f};
+    Vector2 circlePos = (Vector2){40.0f, (float)screenHeight*0.5f};
     float circleSpeed = 1.0f;
 
     // RenderTexture to apply the postprocessing later
@@ -67,37 +67,47 @@ int main(void)
     // Main game loop
     while (!WindowShouldClose())    // Detect window close button or ESC key
     {
+    
         // Update
         //----------------------------------------------------------------------------------
+        if (IsKeyPressed(KEY_LEFT) && fontSize > 9.0) fontSize -= 1;  // Reduce fontSize
+
+        if (IsKeyPressed(KEY_RIGHT) && fontSize < 15.0) fontSize += 1;  // Increase fontSize
+
+        if (circlePos.x > 200.0f || circlePos.x < 40.0f) circleSpeed *= -1; // Revert speed
+
         circlePos.x += circleSpeed;
-        
-        if ((circlePos.x > 200.0f) || (circlePos.x < 40.0f)) circleSpeed *= -1;
-        //----------------------------------------------------------------------------------
+
+        // Set fontsize for the shader
+        SetShaderValue(shader, fontSizeLoc, &fontSize, SHADER_UNIFORM_FLOAT);
 
         // Draw
         //----------------------------------------------------------------------------------
-        // Draw our scene to a render texture first
+
         BeginTextureMode(target);
-            ClearBackground(WHITE);
-            
+            ClearBackground(WHITE); // The background of the scene itself
+
+            // Samples Using custom shader
             DrawTexture(fudesumi, 500, -30, WHITE);
             DrawTextureV(raysan, circlePos, WHITE);
-        
+
         EndTextureMode();
-        
         BeginDrawing();
+
             ClearBackground(RAYWHITE);
 
             BeginShaderMode(shader);
-                // Draw the render texture containing scene
-                // The shader will process every pixel on the screen
-                DrawTextureRec(target.texture,
-                    (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, 
-                    (Vector2){ 0, 0 }, WHITE);
+
+                // Draw the scene texture (that we rendered earlier) to the screen
+                // The shader will process every pixel of this texture
+                DrawTextureRec(target.texture, 
+                               (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, 
+                               (Vector2){ 0, 0 }, 
+                               WHITE);
             EndShaderMode();
 
             DrawRectangle(0, 0, screenWidth, 40, BLACK);
-            DrawText("Ascii effect", 120, 10, 20, LIGHTGRAY);
+            DrawText(TextFormat("Ascii effect - FontSize:%2.0f - [Left] -1 [Right] +1 ", fontSize), 120, 10, 20, LIGHTGRAY);
             DrawFPS(10, 10);
 
         EndDrawing();

BIN
examples/shaders/shaders_ascii_rendering.png