├── .gitattributes ├── .gitignore ├── LICENSE ├── Mandelbrot_set.cpp ├── Mandelbrot_set.hpp ├── Mandelbrot_set_cuda.sln ├── Mandelbrot_set_cuda.vcxproj ├── Mandelbrot_set_cuda.vcxproj.filters ├── README.md ├── Utility.hpp ├── graphics ├── font │ └── Roboto-Regular.ttf └── vid │ └── demo.gif ├── kernel.cu ├── kernel.cuh ├── main.cpp └── main.hpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb 341 | 342 | # VsCode 343 | .vscode 344 | 345 | /include/SFML 346 | /lib 347 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Tend 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mandelbrot_set.cpp: -------------------------------------------------------------------------------- 1 | #include "Mandelbrot_set.hpp" 2 | 3 | using namespace ms; 4 | 5 | Mandelbrot_set::Mandelbrot_set(sf::RenderWindow* window, int width, int height, sf::Vertex* vertices) { 6 | this->width = width; 7 | this->height = height; 8 | this->window = window; 9 | this->vertices = vertices; 10 | } 11 | 12 | void Mandelbrot_set::show() 13 | { 14 | //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); 15 | 16 | int* result = mendelbrot_kernel(height, width, maxIter, startX, startY, zoom); 17 | for (int x = 0; x < (*window).getSize().x; ++x) 18 | { 19 | for (int y = 0; y < (*window).getSize().y; ++y) 20 | { 21 | int i = x + y * width; 22 | 23 | #ifdef __STATIC_MAX_ITER 24 | vertices[i].color.r = palette[result[i]].r; 25 | vertices[i].color.g = palette[result[i]].g; 26 | vertices[i].color.b = palette[result[i]].b; 27 | #else 28 | double iterationNorm = 360.0 * result[i] / maxIter; 29 | if (result[i]) 30 | vertices[i].color = hsv2rgb_fast(iterationNorm); 31 | else 32 | vertices[i].color = sf::Color::Black; 33 | #endif 34 | } 35 | } 36 | cudaFreeHost(result); 37 | (*window).draw(vertices, width * height, sf::Points); 38 | if (isHUDshown) showHUD(); 39 | 40 | (*window).display(); 41 | 42 | //std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 43 | //std::cout << "Time enlapsed: " << std::chrono::duration_cast(end - begin).count() << "[microseconds]" << std::endl; 44 | } 45 | 46 | void Mandelbrot_set::showHUD() { 47 | sf::Font font; 48 | font.loadFromFile("graphics/font/Roboto-Regular.ttf"); 49 | 50 | char str[128]; 51 | snprintf(str, 127, "OffsetX: %.2f OffsetY: %.2f\nZoom: %.4f\nMax iteration: %d", startX, startY, zoom, maxIter); 52 | 53 | sf::RectangleShape rect(sf::Vector2f(450, 100)); 54 | 55 | sf::Text text; 56 | text.setFont(font); 57 | text.setString(str); 58 | text.setCharacterSize(24); 59 | text.setFillColor(sf::Color::Black); 60 | text.setStyle(sf::Text::Bold); 61 | (*window).draw(rect); 62 | (*window).draw(text); 63 | } 64 | 65 | void Mandelbrot_set::setZoom(double modifier) { 66 | zoom *= modifier; 67 | show(); 68 | } 69 | 70 | void Mandelbrot_set::setStartX(double modifier) { 71 | setPosition(modifier, 0); 72 | } 73 | 74 | void Mandelbrot_set::setStartY(double modifier) { 75 | setPosition(0, modifier); 76 | } 77 | 78 | void Mandelbrot_set::setPosition(double modifierX, double modifierY) { 79 | startX += modifierX * zoom; 80 | startY += modifierY * zoom; 81 | show(); 82 | } 83 | 84 | void Mandelbrot_set::setIteration(int modifier) { 85 | if (modifier < 0 && maxIter > 1) 86 | maxIter += modifier; 87 | else if (modifier > 0 && maxIter < 199) 88 | maxIter += modifier; 89 | show(); 90 | } 91 | 92 | void Mandelbrot_set::invertHUD() { 93 | isHUDshown = !isHUDshown; 94 | show(); 95 | } 96 | 97 | void Mandelbrot_set::reset() { 98 | startX = startY = 0.0; 99 | zoom = 1.0; 100 | maxIter = 100; 101 | show(); 102 | } 103 | 104 | sf::Color Mandelbrot_set::hsv2rgb(double h, double s, double v) { 105 | double C, X, Y, Z, H; 106 | short i; 107 | sf::Color out; 108 | 109 | h /= 60.0; 110 | i = (short)(h); 111 | H = h - i; 112 | C = v * 255; 113 | X = C * (1.0 - s); 114 | Y = C * (1.0 - s * H); 115 | Z = C * (1.0 - s * (1 - H)); 116 | 117 | switch (i) 118 | { 119 | case 0: 120 | out.r = C; 121 | out.g = Z; 122 | out.b = X; 123 | break; 124 | case 1: 125 | out.r = Y; 126 | out.g = C; 127 | out.b = Z; 128 | break; 129 | case 2: 130 | out.r = X; 131 | out.g = C; 132 | out.b = Z; 133 | break; 134 | case 3: 135 | out.r = X; 136 | out.g = Y; 137 | out.b = C; 138 | break; 139 | case 4: 140 | out.r = Z; 141 | out.g = X; 142 | out.b = C; 143 | break; 144 | case 5: 145 | default: 146 | out.r = C; 147 | out.g = X; 148 | out.b = Y; 149 | break; 150 | } 151 | return out; 152 | } 153 | 154 | sf::Color Mandelbrot_set::hsv2rgb_fast(double h) { 155 | const double C = 255.0; 156 | double X, Y, Z, H; 157 | short i; 158 | sf::Color out; 159 | 160 | h /= 60.0; 161 | i = (short)(h); 162 | H = h - i; 163 | X = 0.0; 164 | Y = C * (1.0 - H); 165 | Z = C * H; 166 | 167 | switch (i) 168 | { 169 | case 0: 170 | out.r = C; 171 | out.g = Z; 172 | out.b = X; 173 | break; 174 | case 1: 175 | out.r = Y; 176 | out.g = C; 177 | out.b = Z; 178 | break; 179 | case 2: 180 | out.r = X; 181 | out.g = C; 182 | out.b = Z; 183 | break; 184 | case 3: 185 | out.r = X; 186 | out.g = Y; 187 | out.b = C; 188 | break; 189 | case 4: 190 | out.r = Z; 191 | out.g = X; 192 | out.b = C; 193 | break; 194 | case 5: 195 | default: 196 | out.r = C; 197 | out.g = X; 198 | out.b = Y; 199 | break; 200 | } 201 | return out; 202 | } -------------------------------------------------------------------------------- /Mandelbrot_set.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MANDELBROT_SET 2 | #define __MANDELBROT_SET 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "kernel.cuh" 8 | 9 | 10 | namespace ms { 11 | //////////////////////////////////////////////////////////// 12 | /// Class used to easily manage all the data related to the visualization of the Mandelbrot_set 13 | //////////////////////////////////////////////////////////// 14 | class Mandelbrot_set 15 | { 16 | private: 17 | #ifdef __STATIC_MAX_ITER 18 | //////////////////////////////////////////////////////////// 19 | /// Struct containing the r g b data of a color 20 | //////////////////////////////////////////////////////////// 21 | struct ColorData { int r, g, b; }; 22 | //////////////////////////////////////////////////////////// 23 | /// Precompiled palette to achieve top performance. 24 | /// The max_iteration must be set to 100 25 | //////////////////////////////////////////////////////////// 26 | ColorData palette[100] = { {0, 0, 0}, 27 | {255, 15, 0}, {255, 30, 0}, {255, 45, 0}, 28 | {255, 61, 0}, {255, 76, 0}, {255, 91, 0}, 29 | {255, 107, 0}, {255, 122, 0}, {255, 137, 0}, 30 | {255, 153, 0}, {255, 168, 0}, {255, 183, 0}, 31 | {255, 198, 0}, {255, 214, 0}, {255, 229, 0}, 32 | {255, 244, 0}, {249, 255, 5}, {234, 255, 20}, 33 | {219, 255, 35}, {204, 255, 50}, {188, 255, 66}, 34 | {173, 255, 81}, {158, 255, 96}, {142, 255, 112}, 35 | {127, 255, 127}, {112, 255, 142}, {96, 255, 158}, 36 | {81, 255, 173}, {66, 255, 188}, {50, 255, 204}, 37 | {35, 255, 219}, {20, 255, 234}, {5, 255, 249}, 38 | {0, 255, 10}, {0, 255, 25}, {0, 255, 40}, 39 | {0, 255, 56}, {0, 255, 71}, {0, 255, 86}, 40 | {0, 255, 101}, {0, 255, 117}, {0, 255, 132}, 41 | {0, 255, 147}, {0, 255, 163}, {0, 255, 178}, 42 | {0, 255, 193}, {0, 255, 209}, {0, 255, 224}, 43 | {0, 255, 239}, {0, 255, 255}, {0, 239, 255}, 44 | {0, 224, 255}, {0, 209, 255}, {0, 193, 255}, 45 | {0, 178, 255}, {0, 163, 255}, {0, 147, 255}, 46 | {0, 132, 255}, {0, 117, 255}, {0, 101, 255}, 47 | {0, 86, 255}, {0, 71, 255}, {0, 56, 255}, 48 | {0, 40, 255}, {0, 25, 255}, {0, 10, 255}, 49 | {5, 0, 255}, {20, 0, 255}, {35, 0, 255}, 50 | {51, 0, 255}, {66, 0, 255}, {81, 0, 255}, 51 | {96, 0, 255}, {112, 0, 255}, {127, 0, 255}, 52 | {142, 0, 255}, {158, 0, 255}, {173, 0, 255}, 53 | {188, 0, 255}, {203, 0, 255}, {219, 0, 255}, 54 | {234, 0, 255}, {249, 0, 255}, {255, 0, 244}, 55 | {255, 0, 229}, {255, 0, 214}, {255, 0, 198}, 56 | {255, 0, 183}, {255, 0, 168}, {255, 0, 152}, 57 | {255, 0, 137}, {255, 0, 122}, {255, 0, 107}, 58 | {255, 0, 91}, {255, 0, 76}, {255, 0, 61}, 59 | {255, 0, 45}, {255, 0, 30}, {255, 0, 15}, 60 | }; 61 | #endif 62 | //////////////////////////////////////////////////////////// 63 | /// Pixel width of the screen 64 | //////////////////////////////////////////////////////////// 65 | int width; 66 | //////////////////////////////////////////////////////////// 67 | /// Pixel height of the screen 68 | //////////////////////////////////////////////////////////// 69 | int height; 70 | //////////////////////////////////////////////////////////// 71 | /// Maximum number of iterations per pixel 72 | //////////////////////////////////////////////////////////// 73 | int maxIter = 100; 74 | //////////////////////////////////////////////////////////// 75 | /// Horizontal offset 76 | //////////////////////////////////////////////////////////// 77 | double startX = 0.0; 78 | //////////////////////////////////////////////////////////// 79 | /// Vertical offset 80 | //////////////////////////////////////////////////////////// 81 | double startY = 0.0; 82 | //////////////////////////////////////////////////////////// 83 | /// Zoom coefficient 84 | //////////////////////////////////////////////////////////// 85 | double zoom = 1; 86 | //////////////////////////////////////////////////////////// 87 | /// Whether or not to show the HUD 88 | //////////////////////////////////////////////////////////// 89 | bool isHUDshown = true; 90 | //////////////////////////////////////////////////////////// 91 | /// Render window 92 | //////////////////////////////////////////////////////////// 93 | sf::RenderWindow* window; 94 | //////////////////////////////////////////////////////////// 95 | /// Array of verices that represent each pixel on the screen 96 | //////////////////////////////////////////////////////////// 97 | sf::Vertex* vertices; 98 | //////////////////////////////////////////////////////////// 99 | /// 100 | /// Given the h v s values, converts those in the 101 | /// equivalent r g b values and returns the corrisponding 102 | /// sf::Color 103 | /// 104 | /// \param h Hue 105 | /// \param s Saturation 106 | /// \param v Value 107 | /// 108 | /// \return equivalent rgb color 109 | /// 110 | //////////////////////////////////////////////////////////// 111 | sf::Color hsv2rgb(double h, double s, double v); 112 | //////////////////////////////////////////////////////////// 113 | /// 114 | /// Given the h value and considering both s and v as 1, 115 | /// converts those in the equivalent r g b values and 116 | /// returns the corrisponding sf::Color 117 | /// 118 | /// \param h Hue 119 | /// 120 | /// \return equivalent rgb color 121 | /// 122 | //////////////////////////////////////////////////////////// 123 | sf::Color hsv2rgb_fast(double h); 124 | //////////////////////////////////////////////////////////// 125 | /// 126 | /// Displays the HUD with some info about this object 127 | /// 128 | //////////////////////////////////////////////////////////// 129 | void showHUD(); 130 | public: 131 | //////////////////////////////////////////////////////////// 132 | /// 133 | /// Mandelbrot_set contructor. 134 | /// Initializes the internal fields to match the provided 135 | /// arguments 136 | /// 137 | /// \param window Render window 138 | /// \param widht Pixel width of the screen 139 | /// \param height Pixel height of the screen 140 | /// \param vertices Array of verices that represent each pixel on the screen 141 | /// 142 | //////////////////////////////////////////////////////////// 143 | Mandelbrot_set(sf::RenderWindow* window, int widht, int height, sf::Vertex* vertices); 144 | //////////////////////////////////////////////////////////// 145 | /// 146 | /// Displays the Mandelbrot_set on screen after 147 | /// calculating the needed values with the CUDA kernel 148 | /// 149 | //////////////////////////////////////////////////////////// 150 | void show(); 151 | //////////////////////////////////////////////////////////// 152 | /// 153 | /// Adds to the current startX and startY the corriponding 154 | /// modifier value and immediatly shows the updated result 155 | /// 156 | /// \param modifierX Value to add to startX 157 | /// \param modifierY Value to add to startY 158 | /// 159 | //////////////////////////////////////////////////////////// 160 | void setPosition(double modifierX, double modfierY); 161 | //////////////////////////////////////////////////////////// 162 | /// 163 | /// Adds to the current startX the modifier value 164 | /// and immediatly shows the updated result 165 | /// 166 | /// \param modifier Value to add to startX 167 | /// 168 | //////////////////////////////////////////////////////////// 169 | void setStartX(double modifier); 170 | //////////////////////////////////////////////////////////// 171 | /// 172 | /// Adds to the current startY the modifier value 173 | /// and immediatly shows the updated result 174 | /// 175 | /// \param modifier Value to add to startY 176 | /// 177 | //////////////////////////////////////////////////////////// 178 | void setStartY(double modifier); 179 | //////////////////////////////////////////////////////////// 180 | /// 181 | /// Multiplies the current zoom by modifier value 182 | /// and immediatly shows the updated result 183 | /// 184 | /// \param modifier Coefficient to apply to zoom 185 | /// 186 | //////////////////////////////////////////////////////////// 187 | void setZoom(double modifier); 188 | //////////////////////////////////////////////////////////// 189 | /// 190 | /// Adds the modifier value to the current maxIter 191 | /// and immediatly shows the updated result 192 | /// 193 | /// \param modifier Value to add to maxIter 194 | /// 195 | //////////////////////////////////////////////////////////// 196 | void setIteration(int modifier); 197 | //////////////////////////////////////////////////////////// 198 | /// 199 | /// Hides the HUD if it was visible and makes it visible if 200 | /// it was hidden and immediatly shows the updated result 201 | /// 202 | //////////////////////////////////////////////////////////// 203 | void invertHUD(); 204 | //////////////////////////////////////////////////////////// 205 | /// 206 | /// Resets all the values of the object 207 | /// 208 | //////////////////////////////////////////////////////////// 209 | void reset(); 210 | }; 211 | } 212 | #endif // __MANDELBROT_SET 213 | 214 | -------------------------------------------------------------------------------- /Mandelbrot_set_cuda.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mandelbrot_set_cuda", "Mandelbrot_set_cuda.vcxproj", "{9999C41C-9D2F-49C1-BF53-8D5C6C1140F3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9999C41C-9D2F-49C1-BF53-8D5C6C1140F3}.Debug|x64.ActiveCfg = Debug|x64 15 | {9999C41C-9D2F-49C1-BF53-8D5C6C1140F3}.Debug|x64.Build.0 = Debug|x64 16 | {9999C41C-9D2F-49C1-BF53-8D5C6C1140F3}.Release|x64.ActiveCfg = Release|x64 17 | {9999C41C-9D2F-49C1-BF53-8D5C6C1140F3}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {DE594AD4-A03C-479E-9101-04E303518E2C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Mandelbrot_set_cuda.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {9999C41C-9D2F-49C1-BF53-8D5C6C1140F3} 15 | Mandelbrot_set_cuda 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | v142 23 | 24 | 25 | Application 26 | false 27 | true 28 | MultiByte 29 | v142 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | 47 | Level3 48 | Disabled 49 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 50 | $(ProjectDir)\include;%(AdditionalIncludeDirectories) 51 | 52 | 53 | true 54 | Console 55 | sfml-system-d.lib;sfml-window-d.lib;sfml-graphics-d.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 56 | $(ProjectDir)\lib;%(AdditionalLibraryDirectories) 57 | 58 | 59 | 64 60 | 61 | 62 | 63 | 64 | Level3 65 | MaxSpeed 66 | true 67 | true 68 | SFML_STATIC;WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 69 | $(ProjectDir)\include;%(AdditionalIncludeDirectories) 70 | 71 | 72 | true 73 | true 74 | true 75 | Console 76 | sfml-system-s.lib;sfml-window-s.lib;sfml-graphics-s.lib;opengl32.lib;winmm.lib;gdi32.lib;freetype.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 77 | $(ProjectDir)\lib;%(AdditionalLibraryDirectories) 78 | 79 | 80 | 64 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /Mandelbrot_set_cuda.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | src 6 | 7 | 8 | src 9 | 10 | 11 | 12 | 13 | src\Header 14 | 15 | 16 | src\Header 17 | 18 | 19 | src\Header 20 | 21 | 22 | src\Header 23 | 24 | 25 | 26 | 27 | {63033227-7099-4e51-b98c-9d78b4664b90} 28 | 29 | 30 | {e85415d7-b70a-4b57-ba3c-795d71608afe} 31 | 32 | 33 | 34 | 35 | src 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mandelbrot set CUDA 2 | The aim of this project is just for me to practice CUDA programming while trying some fun ideas. 3 | 4 | ### :eyes: Preview 5 | ![](graphics/vid/demo.gif) 6 | 7 | ### Commands: 8 | | Move | Zoom in/out | Increase/Decrease max iteration | Reset | Hide/Show HUD | 9 | | :---: | :---: | :---: | :---: | :---: | 10 | | L-click or WASD or Arrows| Mousewheel or +/- | E/Q | R | H | 11 | 12 | ## :wrench: Requirements 13 | The project written in c++ and uses: 14 | - [CUDA](https://developer.nvidia.com/cuda-zone) 15 | - [SFML](https://www.sfml-dev.org/index.php) 16 | 17 | ## :keycap_ten: On windows (See master branch) 18 | Things to download: 19 | - [CUDA](https://developer.nvidia.com/cuda-downloads) 20 | - [SFML](https://www.sfml-dev.org/download.php) 21 | - [Visual Studio](https://visualstudio.microsoft.com/it/downloads/) (for its MSVC compiler) 22 | 23 | The program uses the standard CUDA libraries and some SFML libraries. 24 | All SFML libraries can be both static or dynamic and each has a debug version (just add a -d at the end). 25 | You should use the debug version when compiling in DEBUG. 26 | 27 | Before compiling, make sure that the paths to the SFML libraries and headers you downloaded are correct. 28 | 29 | ### For the _dynamic_ linking you will need the following libraries (in VS you need to add .lib): 30 | - sfml-graphics 31 | - sfml-system 32 | - sfml-window 33 | 34 | The executable will need the following dll(s) to run: 35 | - sfml-graphics-2.dll 36 | - sfml-system-2.dll 37 | - sfml-window-2.dll 38 | 39 | ### For the _static_ linking you will need the following libraries (in VS you need to add .lib): 40 | - sfml-graphics-s 41 | - sfml-system-s 42 | - sfml-window-s 43 | - opengl32 44 | - winmm 45 | - gdi32 46 | - freetype 47 | 48 | The following flag must be set: 49 | - SFML_STATIC 50 | 51 | ### **Some intersting findings that may act as troubleshooting** 52 | - CUDA on windows **needs** the MSVC compiler, so you don't have the choice to use mingw 53 | - All the lib(s) and dll(s) in SFML have a debug version. You just need to add -d before the extension. You should use this version when compiling with the DEBUG flag 54 | - If you want to use the static linking, make sure that you are compiling in _release_ mode, since otherwise the SFML libraries may conflict with the CUDA ones 55 | 56 | ## :penguin: On linux (See linux branch) 57 | Things to download: 58 | - [CUDA](https://developer.nvidia.com/cuda-downloads) 59 | - [SFML](https://www.sfml-dev.org/download.php) 60 | 61 | The program uses the standard CUDA libraries and some SFML libraries. 62 | Make sure that the paths to the SFML libraries and headers you downloaded is accessible to the nvidia compiler. 63 | 64 | On linux, using static libraries is usually discuraged, so SFML provides only the dynamic version. You can, however, compile your own static libraries ([guide](https://www.sfml-dev.org/tutorials/2.5/compile-with-cmake.php)) 65 | 66 | ### For the _dynamic_ linking you will need the following libraries: 67 | - sfml-graphics 68 | - sfml-system 69 | - sfml-window 70 | 71 | The executable will need the following .so to run: 72 | - sfml-graphics.so.2.5 73 | - sfml-system.so.2.5 74 | - sfml-window.so.2.5 75 | 76 | Run `sh start.sh -h` to know what flags you may want to add, then run `sh start.sh [flags]` with the desired flags. 77 | You can also run the nvcc compiler yourself. -------------------------------------------------------------------------------- /Utility.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __UTILITY 2 | #define __UTILITY 3 | #include 4 | 5 | //////////////////////////////////////////////////////////// 6 | /// 7 | /// Overrides the << operator to print sf::Color, 8 | /// printing the r g b and a values of the color variable 9 | /// 10 | /// \param os Left operand 11 | /// \param c Right operand 12 | /// 13 | /// \return output stream 14 | /// 15 | //////////////////////////////////////////////////////////// 16 | std::ostream& operator<<(std::ostream& os, const sf::Color& c) 17 | { 18 | os << "r:" << c.r << " g:" << c.g << " b:" << c.b << " a:" << c.a; 19 | return os; 20 | } 21 | #endif // __UTILITY -------------------------------------------------------------------------------- /graphics/font/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TendTo/MandelbrotSetCUDA/7b365e5c1069ea78fa931563e301e8b562e5f86e/graphics/font/Roboto-Regular.ttf -------------------------------------------------------------------------------- /graphics/vid/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TendTo/MandelbrotSetCUDA/7b365e5c1069ea78fa931563e301e8b562e5f86e/graphics/vid/demo.gif -------------------------------------------------------------------------------- /kernel.cu: -------------------------------------------------------------------------------- 1 | #include "kernel.cuh" 2 | 3 | void error(char const* str) 4 | { 5 | fprintf(stderr, "%s\n", str); 6 | exit(1); 7 | } 8 | 9 | void cuda_check(cudaError_t err, char const* str) 10 | { 11 | if (err != cudaSuccess) { 12 | fprintf(stderr, "%s: CUDA error %d (%s)\n", 13 | str, err, cudaGetErrorString(err)); 14 | } 15 | } 16 | 17 | __global__ void fractal(int nrows, int ncols, int max_iter, double startX, double startY, double zoom, int* result) //373 - 326 18 | { 19 | int x_idx = threadIdx.x + blockIdx.x * blockDim.x; 20 | int y_idx = threadIdx.y + blockIdx.y * blockDim.y; 21 | if (x_idx >= ncols || y_idx >= nrows) 22 | return; 23 | 24 | int l = x_idx + y_idx * ncols; 25 | double x = ((x_idx - ncols / 2) * zoom + startX) / ncols * 3.5 - 0.75; 26 | double y = ((y_idx - nrows / 2) * zoom + startY) / nrows * 2.0; 27 | double re = x, im = y; 28 | for (int i = 1; i < max_iter; ++i) 29 | { 30 | if (re * re + im * im >= 4) 31 | { 32 | result[l] = i; 33 | return; 34 | } 35 | double reTemp = re * re - im * im + x; 36 | im = 2 * re * im + y; 37 | re = reTemp; 38 | } 39 | result[l] = 0; 40 | } 41 | 42 | #if __DEBUG 43 | __global__ void fractal_old(int nrows, int ncols, int* result) //398.86642 - 343.53 44 | { 45 | int x_idx = threadIdx.x + blockIdx.x * blockDim.x; 46 | int y_idx = threadIdx.y + blockIdx.y * blockDim.y; 47 | if (x_idx >= nrows || y_idx >= ncols) 48 | return; 49 | 50 | int l = x_idx * ncols + y_idx; 51 | double x = (double)x_idx / nrows * 3.5 - 2.5; 52 | double y = (double)y_idx / ncols * 2.0 - 1.0; 53 | double re = x, im = y; 54 | for (int i = 1; i < MAX_ITERATIONS; ++i) 55 | { 56 | if (re * re + im * im >= 4) 57 | { 58 | result[l] = i; 59 | return; 60 | } 61 | double reTemp = re * re - im * im + x; 62 | im = 2 * re * im + y; 63 | re = reTemp; 64 | } 65 | result[l] = 0; 66 | } 67 | #endif 68 | 69 | int* mendelbrot_kernel(int nrows, int ncols, int max_iter, double startX, double startY, double zoom) 70 | { 71 | cudaError_t err; 72 | cudaEvent_t start, end; 73 | int* d_result, * h_result; 74 | size_t res_size = nrows * ncols * sizeof(int); 75 | float time; 76 | 77 | err = cudaMalloc(&d_result, res_size); 78 | cuda_check(err, "cudaMalloc"); 79 | err = cudaMallocHost(&h_result, res_size); 80 | cuda_check(err, "cudaMallocHost"); 81 | 82 | cudaEventCreate(&start); 83 | cudaEventCreate(&end); 84 | 85 | dim3 dimBlock(32, 32); 86 | dim3 dimGrid((ncols + 31) / 32, (nrows + 31) / 32); 87 | 88 | cudaEventRecord(start); 89 | fractal << > > (nrows, ncols, max_iter, startX, startY, zoom, d_result); 90 | cudaEventRecord(end); 91 | 92 | 93 | err = cudaMemcpy(h_result, d_result, res_size, cudaMemcpyDeviceToHost); 94 | cuda_check(err, "cudaMalloc"); 95 | 96 | err = cudaEventSynchronize(end); 97 | cuda_check(err, "sync"); 98 | 99 | cudaEventElapsedTime(&time, start, end); 100 | //printf("Tempo passato = %f\n", time); 101 | 102 | err = cudaFree(d_result); 103 | cuda_check(err, "cudaFree"); 104 | 105 | return h_result; 106 | } 107 | 108 | #if __DEBUG 109 | int main() 110 | { 111 | int* result = kernel_start(12000, 8000); 112 | //int* result = kernel_start(); 113 | 114 | // for (int j = NCOLS - 1; j >= 0; --j) 115 | // { 116 | // for (int i = 0; i < NROWS; i++) 117 | // { 118 | // printf("%d ", result[i * NCOLS + j]); 119 | // } 120 | // printf("\n"); 121 | // } 122 | 123 | // for (int j = 0; j < NROWS; ++j) 124 | // { 125 | // for (int i = 0; i < NCOLS; ++i) 126 | // { 127 | // printf("%d ", result[j * NCOLS + i]); 128 | // } 129 | // printf("\n"); 130 | // } 131 | return 0; 132 | } 133 | #endif -------------------------------------------------------------------------------- /kernel.cuh: -------------------------------------------------------------------------------- 1 | #ifndef __KERNEL_CUDA 2 | #define __KERNEL_CUDA 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | //////////////////////////////////////////////////////////// 10 | /// 11 | /// Starts the CUDA kernel with the given inputs 12 | /// 13 | /// \param nrows Number of rows (height) 14 | /// \param ncols Number of columns (width) 15 | /// \param max_iter Max number of iterations per pixel 16 | /// \param startX Horizontal offset 17 | /// \param startY Vertical offset 18 | /// \param zoom Zoom coefficient 19 | /// 20 | /// \return Array of size (nrows * ncols) containing the number of iteration per point if it is less than max_iter, 0 otherwise 21 | /// 22 | //////////////////////////////////////////////////////////// 23 | int* mendelbrot_kernel(int nrows, int ncols, int max_iter, double startX, double startY, double zoom); 24 | 25 | #endif // __KERNEL_PRO_ -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.hpp" 2 | 3 | int main() 4 | { 5 | initWindow(); 6 | return 0; 7 | } 8 | 9 | void initWindow() 10 | { 11 | bool isHUDPressed = false; 12 | sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Mandelbrot set", sf::Style::Fullscreen); 13 | sf::Vertex* vertices = initVertices(); 14 | ms::Mandelbrot_set mandelbrot(&window, WIDTH, HEIGHT, vertices); 15 | 16 | window.clear(); 17 | mandelbrot.show(); 18 | 19 | while (window.isOpen()) 20 | { 21 | sf::Event event; 22 | while (window.pollEvent(event)) 23 | { 24 | if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) 25 | window.close(); 26 | if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) 27 | { 28 | mandelbrot.setPosition(sf::Mouse::getPosition(window).x - (int)(window.getSize().x >> 1), sf::Mouse::getPosition(window).y - (int)(window.getSize().y >> 1)); 29 | } 30 | if (event.type == sf::Event::MouseWheelMoved) 31 | { 32 | if (event.mouseWheel.delta > 0) 33 | mandelbrot.setZoom(0.9); 34 | else 35 | mandelbrot.setZoom(1.1); 36 | } 37 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { 38 | mandelbrot.setStartY(-100); 39 | } 40 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { 41 | mandelbrot.setStartY(100); 42 | } 43 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { 44 | mandelbrot.setStartX(-100); 45 | } 46 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { 47 | mandelbrot.setStartX(100); 48 | } 49 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Add)) { 50 | mandelbrot.setZoom(0.9); 51 | } 52 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Subtract)) { 53 | mandelbrot.setZoom(1.1); 54 | } 55 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::R)) { 56 | mandelbrot.reset(); 57 | } 58 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::E)) { 59 | mandelbrot.setIteration(1); 60 | } 61 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { 62 | mandelbrot.setIteration(-1); 63 | } 64 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::H)) { 65 | if (!isHUDPressed) { 66 | isHUDPressed = true; 67 | mandelbrot.invertHUD(); 68 | } 69 | } 70 | else 71 | isHUDPressed = false; 72 | } 73 | } 74 | } 75 | 76 | sf::Vertex* initVertices() 77 | { 78 | sf::Vertex* vertices = new sf::Vertex[WIDTH * HEIGHT]; 79 | for (int x = 0; x < WIDTH; ++x) 80 | { 81 | for (int y = 0; y < HEIGHT; ++y) { 82 | vertices[x + y * WIDTH].position = sf::Vector2f(x, y); 83 | vertices[x + y * WIDTH].color = sf::Color(x, y, 0); 84 | } 85 | } 86 | return vertices; 87 | } 88 | 89 | #if __DEBUG 90 | void fractal(sf::RenderWindow& window, sf::Vertex* vertices, int startX, int startY, double zoom) // 15 * 10^5 micro sec 91 | { 92 | std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); 93 | sf::Color color; 94 | double divX = window.getSize().x / 3.5; 95 | double divY = window.getSize().y / 2.0; 96 | for (int x = 0; x < window.getSize().x; ++x) 97 | { 98 | for (int y = 0; y < window.getSize().y; ++y) 99 | { 100 | double internalX = (x * zoom + startX) / divX - 2.5; 101 | double internalY = (y * zoom + startY) / divY - 1.0; 102 | double re = internalX; 103 | double im = internalY; 104 | int iteration = 1; 105 | while (re * re + im * im <= 4 && iteration < MAX_ITER) 106 | { 107 | double reTemp = re * re - im * im + internalX; 108 | im = 2 * re * im + internalY; 109 | re = reTemp; 110 | iteration++; 111 | } 112 | double iterationNorm = iteration / (double)MAX_ITER; 113 | color = hsv2rgb_s1(iterationNorm * 360.0, iteration < MAX_ITER ? 1.0 : 0.0); 114 | vertices[x + y * WIDTH].color = color; 115 | } 116 | } 117 | window.draw(vertices, WIDTH * HEIGHT, sf::Points); 118 | window.display(); 119 | std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 120 | std::cout << "Time enlapsed CPU: " << std::chrono::duration_cast(end - begin).count() << "[microseconds]" << std::endl; 121 | } 122 | #endif -------------------------------------------------------------------------------- /main.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __VISUAL 2 | #define __VISUAL 3 | #include 4 | #include "Mandelbrot_set.h" 5 | 6 | #define WIDTH 1920 7 | #define HEIGHT 1080 8 | 9 | //////////////////////////////////////////////////////////// 10 | /// 11 | /// Initializes the Mandelbrot_set object and starts the main loop to handle user's iputs 12 | /// 13 | //////////////////////////////////////////////////////////// 14 | void initWindow(); 15 | 16 | //////////////////////////////////////////////////////////// 17 | /// 18 | /// Initializes an array of size (WIDTH * HEIGHT) containing all the vertices that represent each pixel of the screen 19 | /// 20 | /// \return List of initialized vertices 21 | /// 22 | //////////////////////////////////////////////////////////// 23 | sf::Vertex* initVertices(); 24 | 25 | #endif // __VISUAL 26 | --------------------------------------------------------------------------------