1 | /******************************************************************************************* |
2 | * |
3 | * raylib [shaders] example - julia sets |
4 | * |
5 | * NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, |
6 | * OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. |
7 | * |
8 | * NOTE: Shaders used in this example are #version 330 (OpenGL 3.3). |
9 | * |
10 | * This example has been created using raylib 2.5 (www.raylib.com) |
11 | * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) |
12 | * |
13 | * Example contributed by eggmund (@eggmund) and reviewed by Ramon Santamaria (@raysan5) |
14 | * |
15 | * Copyright (c) 2019 eggmund (@eggmund) and Ramon Santamaria (@raysan5) |
16 | * |
17 | ********************************************************************************************/ |
18 | |
19 | #include "raylib.h" |
20 | |
21 | #if defined(PLATFORM_DESKTOP) |
22 | #define GLSL_VERSION 330 |
23 | #else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB |
24 | #define GLSL_VERSION 100 |
25 | #endif |
26 | |
27 | // A few good julia sets |
28 | const float POINTS_OF_INTEREST[6][2] = |
29 | { |
30 | { -0.348827, 0.607167 }, |
31 | { -0.786268, 0.169728 }, |
32 | { -0.8, 0.156 }, |
33 | { 0.285, 0.0 }, |
34 | { -0.835, -0.2321 }, |
35 | { -0.70176, -0.3842 }, |
36 | }; |
37 | |
38 | int main(void) |
39 | { |
40 | // Initialization |
41 | //-------------------------------------------------------------------------------------- |
42 | const int screenWidth = 800; |
43 | const int screenHeight = 450; |
44 | |
45 | InitWindow(screenWidth, screenHeight, "raylib [shaders] example - julia sets" ); |
46 | |
47 | // Load julia set shader |
48 | // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader |
49 | Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/julia_set.fs" , GLSL_VERSION)); |
50 | |
51 | // c constant to use in z^2 + c |
52 | float c[2] = { POINTS_OF_INTEREST[0][0], POINTS_OF_INTEREST[0][1] }; |
53 | |
54 | // Offset and zoom to draw the julia set at. (centered on screen and default size) |
55 | float offset[2] = { -(float)screenWidth/2, -(float)screenHeight/2 }; |
56 | float zoom = 1.0f; |
57 | |
58 | Vector2 offsetSpeed = { 0.0f, 0.0f }; |
59 | |
60 | // Get variable (uniform) locations on the shader to connect with the program |
61 | // NOTE: If uniform variable could not be found in the shader, function returns -1 |
62 | int cLoc = GetShaderLocation(shader, "c" ); |
63 | int zoomLoc = GetShaderLocation(shader, "zoom" ); |
64 | int offsetLoc = GetShaderLocation(shader, "offset" ); |
65 | |
66 | // Tell the shader what the screen dimensions, zoom, offset and c are |
67 | float screenDims[2] = { (float)screenWidth, (float)screenHeight }; |
68 | SetShaderValue(shader, GetShaderLocation(shader, "screenDims" ), screenDims, UNIFORM_VEC2); |
69 | |
70 | SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); |
71 | SetShaderValue(shader, zoomLoc, &zoom, UNIFORM_FLOAT); |
72 | SetShaderValue(shader, offsetLoc, offset, UNIFORM_VEC2); |
73 | |
74 | // Create a RenderTexture2D to be used for render to texture |
75 | RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); |
76 | |
77 | int incrementSpeed = 0; // Multiplier of speed to change c value |
78 | bool showControls = true; // Show controls |
79 | bool pause = false; // Pause animation |
80 | |
81 | SetTargetFPS(60); // Set our game to run at 60 frames-per-second |
82 | //-------------------------------------------------------------------------------------- |
83 | |
84 | // Main game loop |
85 | while (!WindowShouldClose()) // Detect window close button or ESC key |
86 | { |
87 | // Update |
88 | //---------------------------------------------------------------------------------- |
89 | // Press [1 - 6] to reset c to a point of interest |
90 | if (IsKeyPressed(KEY_ONE) || |
91 | IsKeyPressed(KEY_TWO) || |
92 | IsKeyPressed(KEY_THREE) || |
93 | IsKeyPressed(KEY_FOUR) || |
94 | IsKeyPressed(KEY_FIVE) || |
95 | IsKeyPressed(KEY_SIX)) |
96 | { |
97 | if (IsKeyPressed(KEY_ONE)) c[0] = POINTS_OF_INTEREST[0][0], c[1] = POINTS_OF_INTEREST[0][1]; |
98 | else if (IsKeyPressed(KEY_TWO)) c[0] = POINTS_OF_INTEREST[1][0], c[1] = POINTS_OF_INTEREST[1][1]; |
99 | else if (IsKeyPressed(KEY_THREE)) c[0] = POINTS_OF_INTEREST[2][0], c[1] = POINTS_OF_INTEREST[2][1]; |
100 | else if (IsKeyPressed(KEY_FOUR)) c[0] = POINTS_OF_INTEREST[3][0], c[1] = POINTS_OF_INTEREST[3][1]; |
101 | else if (IsKeyPressed(KEY_FIVE)) c[0] = POINTS_OF_INTEREST[4][0], c[1] = POINTS_OF_INTEREST[4][1]; |
102 | else if (IsKeyPressed(KEY_SIX)) c[0] = POINTS_OF_INTEREST[5][0], c[1] = POINTS_OF_INTEREST[5][1]; |
103 | |
104 | SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); |
105 | } |
106 | |
107 | if (IsKeyPressed(KEY_SPACE)) pause = !pause; // Pause animation (c change) |
108 | if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls |
109 | |
110 | if (!pause) |
111 | { |
112 | if (IsKeyPressed(KEY_RIGHT)) incrementSpeed++; |
113 | else if (IsKeyPressed(KEY_LEFT)) incrementSpeed--; |
114 | |
115 | // TODO: The idea is to zoom and move around with mouse |
116 | // Probably offset movement should be proportional to zoom level |
117 | if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) || IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) |
118 | { |
119 | if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) zoom += zoom*0.003f; |
120 | if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) zoom -= zoom*0.003f; |
121 | |
122 | Vector2 mousePos = GetMousePosition(); |
123 | |
124 | offsetSpeed.x = mousePos.x -(float)screenWidth/2; |
125 | offsetSpeed.y = mousePos.y -(float)screenHeight/2; |
126 | |
127 | // Slowly move camera to targetOffset |
128 | offset[0] += GetFrameTime()*offsetSpeed.x*0.8f; |
129 | offset[1] += GetFrameTime()*offsetSpeed.y*0.8f; |
130 | } |
131 | else offsetSpeed = (Vector2){ 0.0f, 0.0f }; |
132 | |
133 | SetShaderValue(shader, zoomLoc, &zoom, UNIFORM_FLOAT); |
134 | SetShaderValue(shader, offsetLoc, offset, UNIFORM_VEC2); |
135 | |
136 | // Increment c value with time |
137 | float amount = GetFrameTime()*incrementSpeed*0.0005f; |
138 | c[0] += amount; |
139 | c[1] += amount; |
140 | |
141 | SetShaderValue(shader, cLoc, c, UNIFORM_VEC2); |
142 | } |
143 | //---------------------------------------------------------------------------------- |
144 | |
145 | // Draw |
146 | //---------------------------------------------------------------------------------- |
147 | BeginDrawing(); |
148 | |
149 | ClearBackground(BLACK); // Clear the screen of the previous frame. |
150 | |
151 | // Using a render texture to draw Julia set |
152 | BeginTextureMode(target); // Enable drawing to texture |
153 | ClearBackground(BLACK); // Clear the render texture |
154 | |
155 | // Draw a rectangle in shader mode to be used as shader canvas |
156 | // NOTE: Rectangle uses font white character texture coordinates, |
157 | // so shader can not be applied here directly because input vertexTexCoord |
158 | // do not represent full screen coordinates (space where want to apply shader) |
159 | DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK); |
160 | EndTextureMode(); |
161 | |
162 | // Draw the saved texture and rendered julia set with shader |
163 | // NOTE: We do not invert texture on Y, already considered inside shader |
164 | BeginShaderMode(shader); |
165 | DrawTexture(target.texture, 0, 0, WHITE); |
166 | EndShaderMode(); |
167 | |
168 | if (showControls) |
169 | { |
170 | DrawText("Press Mouse buttons right/left to zoom in/out and move" , 10, 15, 10, RAYWHITE); |
171 | DrawText("Press KEY_F1 to toggle these controls" , 10, 30, 10, RAYWHITE); |
172 | DrawText("Press KEYS [1 - 6] to change point of interest" , 10, 45, 10, RAYWHITE); |
173 | DrawText("Press KEY_LEFT | KEY_RIGHT to change speed" , 10, 60, 10, RAYWHITE); |
174 | DrawText("Press KEY_SPACE to pause movement animation" , 10, 75, 10, RAYWHITE); |
175 | } |
176 | |
177 | EndDrawing(); |
178 | //---------------------------------------------------------------------------------- |
179 | } |
180 | |
181 | // De-Initialization |
182 | //-------------------------------------------------------------------------------------- |
183 | UnloadShader(shader); // Unload shader |
184 | UnloadRenderTexture(target); // Unload render texture |
185 | |
186 | CloseWindow(); // Close window and OpenGL context |
187 | //-------------------------------------------------------------------------------------- |
188 | |
189 | return 0; |
190 | } |
191 | |