diff --git a/examples/Makefile b/examples/Makefile index df1980126..fde0dd2ec 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -451,6 +451,7 @@ EXAMPLES = \ shaders/shaders_texture_drawing \ shaders/shaders_texture_waves \ shaders/shaders_julia_set \ + shaders/shaders_eratosthenes \ audio/audio_module_playing \ audio/audio_music_stream \ audio/audio_raw_stream \ diff --git a/examples/shaders/resources/shaders/glsl100/eratosthenes.fs b/examples/shaders/resources/shaders/glsl100/eratosthenes.fs new file mode 100644 index 000000000..0d598cacb --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/eratosthenes.fs @@ -0,0 +1,58 @@ +#version 100 + +precision mediump float; + +/************************************************************************************* + + The Sieve of Eratosthenes -- a simple shader by ProfJski + An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + + The screen is divided into a square grid of boxes, each representing an integer value. + Each integer is tested to see if it is a prime number. Primes are colored white. + Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer. + + You can change the scale variable to make a larger or smaller grid. + Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers. + + WARNING: If you make scale too large, your GPU may bog down! + +***************************************************************************************/ + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Make a nice spectrum of colors based on counter and maxSize +vec4 Colorizer(float counter, float maxSize) +{ + float red = 0.0, green = 0.0, blue = 0.0; + float normsize = counter/maxSize; + + red = smoothstep(0.3, 0.7, normsize); + green = sin(3.14159*normsize); + blue = 1.0 - smoothstep(0.0, 0.4, normsize); + + return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0); +} + +void main() +{ + vec4 color = vec4(1.0); + float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid. + int value = int(scale*floor(fragTexCoord.y*scale) + floor(fragTexCoord.x*scale)); // Group pixels into boxes representing integer values + + if ((value == 0) || (value == 1) || (value == 2)) gl_FragColor = vec4(1.0); + else + { + for (int i = 2; (i < max(2, sqrt(value) + 1)); i++) + { + if ((value - i*floor(value/i)) == 0) + { + color = Colorizer(float(i), scale); + //break; // Uncomment to color by the largest factor instead + } + } + + gl_FragColor = color; + } +} diff --git a/examples/shaders/resources/shaders/glsl330/eratosthenes.fs b/examples/shaders/resources/shaders/glsl330/eratosthenes.fs new file mode 100644 index 000000000..a6390b745 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/eratosthenes.fs @@ -0,0 +1,59 @@ +#version 330 + +/************************************************************************************* + + The Sieve of Eratosthenes -- a simple shader by ProfJski + An early prime number sieve: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + + The screen is divided into a square grid of boxes, each representing an integer value. + Each integer is tested to see if it is a prime number. Primes are colored white. + Non-primes are colored with a color that indicates the smallest factor which evenly divdes our integer. + + You can change the scale variable to make a larger or smaller grid. + Total number of integers displayed = scale squared, so scale = 100 tests the first 10,000 integers. + + WARNING: If you make scale too large, your GPU may bog down! + +***************************************************************************************/ + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +// Make a nice spectrum of colors based on counter and maxSize +vec4 Colorizer(float counter, float maxSize) +{ + float red = 0.0, green = 0.0, blue = 0.0; + float normsize = counter/maxSize; + + red = smoothstep(0.3, 0.7, normsize); + green = sin(3.14159*normsize); + blue = 1.0 - smoothstep(0.0, 0.4, normsize); + + return vec4(0.8*red, 0.8*green, 0.8*blue, 1.0); +} + +void main() +{ + vec4 color = vec4(1.0); + float scale = 1000.0; // Makes 100x100 square grid. Change this variable to make a smaller or larger grid. + int value = int(scale*floor(fragTexCoord.y*scale)+floor(fragTexCoord.x*scale)); // Group pixels into boxes representing integer values + + if ((value == 0) || (value == 1) || (value == 2)) finalColor = vec4(1.0); + else + { + for (int i = 2; (i < max(2, sqrt(value) + 1)); i++) + { + if ((value - i*floor(value/i)) == 0) + { + color = Colorizer(float(i), scale); + //break; // Uncomment to color by the largest factor instead + } + } + + finalColor = color; + } +} diff --git a/examples/shaders/shaders_eratosthenes.c b/examples/shaders/shaders_eratosthenes.c new file mode 100644 index 000000000..bfe516b52 --- /dev/null +++ b/examples/shaders/shaders_eratosthenes.c @@ -0,0 +1,94 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Sieve of Eratosthenes +* +* Sieve of Eratosthenes, the earliest known (ancient Greek) prime number sieve. +* +* "Sift the twos and sift the threes, +* The Sieve of Eratosthenes. +* When the multiples sublime, +* the numbers that are left are prime." +* +* 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). +* +* This example has been created using raylib 2.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Example contributed by ProfJski and reviewed by Ramon Santamaria (@raysan5) +* +* Copyright (c) 2019 ProfJski and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Sieve of Eratosthenes"); + + RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); + + // Load Eratosthenes shader + // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader + Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/eratosthenes.fs", GLSL_VERSION)); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Nothing to do here, everything is happening in the shader + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginTextureMode(target); // Enable drawing to texture + ClearBackground(BLACK); // Clear the render texture + + // Draw a rectangle in shader mode to be used as shader canvas + // NOTE: Rectangle uses font white character texture coordinates, + // so shader can not be applied here directly because input vertexTexCoord + // do not represent full screen coordinates (space where want to apply shader) + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK); + EndTextureMode(); // End drawing to texture (now we have a blank texture available for the shader) + + BeginShaderMode(shader); + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE); + EndShaderMode(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + UnloadRenderTexture(target); // Unload texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_eratosthenes.png b/examples/shaders/shaders_eratosthenes.png new file mode 100644 index 000000000..acd7fc75f Binary files /dev/null and b/examples/shaders/shaders_eratosthenes.png differ