├── .gitattributes ├── .gitignore ├── Images ├── example_impl.png └── screenshot.png ├── LICENSE.txt ├── README.md ├── opengl_textrendering.sln └── opengl_textrendering ├── dlls ├── freetype.dll ├── glew32.dll └── glfw3.dll ├── lib ├── stb_image.h ├── stb_implement.cpp └── stb_implement.h ├── main.cpp ├── opengl_textrendering.vcxproj ├── opengl_textrendering.vcxproj.filters └── src ├── app_window.cpp ├── app_window.h ├── buffers ├── IndexBuffer.cpp ├── IndexBuffer.h ├── Texture.cpp ├── Texture.h ├── VertexArray.cpp ├── VertexArray.h ├── VertexBuffer.cpp ├── VertexBuffer.h ├── VertexBufferLayout.cpp ├── VertexBufferLayout.h ├── gBuffers.cpp ├── gBuffers.h └── junk.cpp ├── font_atlas.cpp ├── font_atlas.h ├── geom_store.cpp ├── geom_store.h ├── label_text_store.cpp ├── label_text_store.h └── shaders ├── basic_frag_shader.frag ├── basic_vert_shader.vert ├── shader.cpp ├── shader.h ├── text_frag_shader.frag ├── text_vert_shader.vert ├── ttf_CanadaDBNormal.ttf ├── ttf_CenturyGothic.ttf ├── ttf_FreeSans.ttf └── ttf_HyperFont.ttf /.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 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /Images/example_impl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/Images/example_impl.png -------------------------------------------------------------------------------- /Images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/Images/screenshot.png -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenGL Text Rendering 2 | 3 | ## Description 4 | This repository offers a highly optimized method for rendering text in Modern OpenGL. By utilizing a font atlas and binding textures only once for an entire group of text, this approach significantly improves efficiency compared to rendering characters individually. This repository can be used as a helpful resource for developers who want to improve the performance of text rendering in their OpenGL projects. 5 | 6 | ## Introduction 7 | Rendering text in OpenGL can be inefficient when using a method that binds textures and vertex/index buffers for every single character. This repository offers an alternative solution for rendering text more efficiently with a single texture and index bind. 8 | 9 | ![Text_Rendering](/Images/screenshot.png) 10 | 11 | ## How It Works 12 | The repository uses Freetype to load the font.ttf file and create an atlas for every character. The atlas stores the character size, bearing, and texture coordinates, and creates a 2D texture with all the textures aligned in a straight manner. By assigning the appropriate texture coordinate when creating the vertex buffer, the method becomes much more efficient. 13 | 14 | The main component for rendering text with a single bind is the Font_atlas.cpp and Font_atlas.h files. 15 | 16 | ## How to Use 17 | To use this repository in your OpenGL project, simply include the Font_atlas.cpp and Font_atlas.h files in your project directory and add them to your project build settings. Then, initialize the font atlas and render your text using the paint_text() function. 18 | 19 | ## Conclusion 20 | By using this repository, you can significantly improve the efficiency of text rendering in your OpenGL projects. 21 | 22 | 23 | ## Example Implementation 24 | 25 | Below is the example implementation in another app. Batch rendering of n-number of text in one draw call. 26 | 27 | ![Example Implementation](/Images/example_impl.png) 28 | -------------------------------------------------------------------------------- /opengl_textrendering.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33627.172 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl_textrendering", "opengl_textrendering\opengl_textrendering.vcxproj", "{454C16CA-D7AA-4407-9CDE-E48D1EE2198D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Debug|x64.ActiveCfg = Debug|x64 17 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Debug|x64.Build.0 = Debug|x64 18 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Debug|x86.Build.0 = Debug|Win32 20 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Release|x64.ActiveCfg = Release|x64 21 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Release|x64.Build.0 = Release|x64 22 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Release|x86.ActiveCfg = Release|Win32 23 | {454C16CA-D7AA-4407-9CDE-E48D1EE2198D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {38E0E19B-2FB7-43AC-8AD3-B21630C35E8D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /opengl_textrendering/dlls/freetype.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/dlls/freetype.dll -------------------------------------------------------------------------------- /opengl_textrendering/dlls/glew32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/dlls/glew32.dll -------------------------------------------------------------------------------- /opengl_textrendering/dlls/glfw3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/dlls/glfw3.dll -------------------------------------------------------------------------------- /opengl_textrendering/lib/stb_implement.cpp: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include "stb_image.h" 3 | #include "stb_implement.h" 4 | 5 | stb_implement::stb_implement(const char* location) 6 | { 7 | // Constructor loads the image to image pointer 8 | int numChannels; 9 | image = stbi_load(location, &image_width, &image_height, &numChannels, 0); 10 | } 11 | 12 | stb_implement::~stb_implement() 13 | { 14 | // Clean up the loaded image data 15 | stbi_image_free(image); 16 | } 17 | -------------------------------------------------------------------------------- /opengl_textrendering/lib/stb_implement.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // can't put #define STB_IMAGE_IMPLEMENTATION in a header file. 3 | // Only one source file can see the #define. 4 | // So the STB implementation is done in stb_implement.cpp to avoid linker error 5 | 6 | class stb_implement 7 | { 8 | public: 9 | unsigned char* image; 10 | int image_width; 11 | int image_height; 12 | 13 | // Constructor and Destructor 14 | stb_implement(const char* location); 15 | 16 | ~stb_implement(); 17 | 18 | // Functions 19 | private: 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /opengl_textrendering/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "src/app_window.h" 3 | 4 | #ifndef WIN32_LEAN_AND_MEAN 5 | #define WIN32_LEAN_AND_MEAN 6 | #endif 7 | 8 | #include 9 | 10 | int main() 11 | { 12 | app_window app; 13 | app.init(); 14 | 15 | if (app.is_glwindow_success == false) 16 | { 17 | // Window creation failed 18 | // Display error in the console 19 | std::cerr << app.log << std::endl; 20 | std::cin.get(); 21 | return -1; 22 | } 23 | else 24 | { 25 | // Window creation successful (Hide the console window) 26 | // ShowWindow(GetConsoleWindow(), SW_HIDE); //SW_RESTORE to bring back 27 | app.app_render(); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /opengl_textrendering/opengl_textrendering.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {454c16ca-d7aa-4407-9cde-e48d1ee2198d} 25 | opengltextrendering 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | C:\openGL\glfw-3.3.8.bin.WIN64\include\;C:\openGL\glew-2.2.0\include\;C:\openGL\glm;C:\openGL\freetype-windows-binaries\include 108 | stdcpp17 109 | 110 | 111 | Console 112 | true 113 | C:\openGL\glew-2.2.0\lib\Release\x64;C:\openGL\glfw-3.3.8.bin.WIN64\lib-vc2022;C:\openGL\freetype-windows-binaries\release dll\win64 114 | $(CoreLibraryDependencies);%(AdditionalDependencies);;glew32.lib;glfw3.lib;opengl32.lib;freetype.lib 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | true 122 | true 123 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /opengl_textrendering/opengl_textrendering.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /opengl_textrendering/src/app_window.cpp: -------------------------------------------------------------------------------- 1 | #include "app_window.h" 2 | 3 | int app_window::window_width = 800; 4 | int app_window::window_height = 600; 5 | bool app_window::isWindowSizeChanging = false; 6 | 7 | app_window::app_window() 8 | { 9 | } 10 | 11 | app_window::~app_window() 12 | { 13 | } 14 | 15 | void app_window::app_render() 16 | { 17 | // glEnable(GL_CULL_FACE); 18 | glEnable(GL_BLEND); 19 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 20 | 21 | // Main rendering loop 22 | while (!glfwWindowShouldClose(window)) 23 | { 24 | 25 | // Render OpenGL graphics here 26 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set the clear color to black 27 | glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer 28 | 29 | 30 | isWindowSizeChanging = false; 31 | 32 | // Paint the geometry 33 | geom.paint_geometry(); 34 | 35 | // Swap buffers 36 | glfwSwapBuffers(window); 37 | 38 | // Poll for events 39 | glfwPollEvents(); 40 | } 41 | 42 | 43 | } 44 | 45 | void app_window::init() 46 | { 47 | // Initialize GLFW 48 | is_glwindow_success = false; 49 | if (!glfwInit()) { 50 | // ShowWindow(GetConsoleWindow(), SW_RESTORE); 51 | log = "Failed to initialize GLFW"; 52 | // std::cerr << "Failed to initialize GLFW" << std::endl; 53 | return; 54 | } 55 | 56 | // Set OpenGL version to 3.3 57 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 58 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 59 | 60 | // Create a window 61 | window = glfwCreateWindow(window_width, window_height, "OpenGL Text Rendering", nullptr, nullptr); 62 | 63 | if (!window) { 64 | log = "Failed to create GLFW window"; 65 | // std::cerr << "Failed to create GLFW window" << std::endl; 66 | glfwTerminate(); 67 | return; 68 | } 69 | 70 | // Make the window's context current 71 | glfwMakeContextCurrent(window); 72 | 73 | // Initialize GLEW 74 | if (glewInit() != GLEW_OK) { 75 | log = "Failed to initialize GLEW"; 76 | // std::cerr << "Failed to initialize GLEW" << std::endl; 77 | glfwTerminate(); 78 | return; 79 | } 80 | 81 | //// Maximize the window 82 | //glfwMaximizeWindow(window); 83 | 84 | // Set viewport size and register framebuffer resize callback 85 | glfwGetFramebufferSize(window, &window_width, &window_height); 86 | glfwSetFramebufferSizeCallback(window, framebufferSizeCallback); 87 | 88 | // Window initialize success 89 | is_glwindow_success = true; 90 | 91 | 92 | framebufferSizeCallback(window, window_width, window_height); 93 | 94 | // Set the geometry 95 | geom.set_geometry(); 96 | } 97 | 98 | 99 | // Static callback function for framebuffer size changes 100 | // static keyword makes the function a class-level function rather than an instance-level function 101 | // allows it to be used as a callback function for the GLFW library 102 | void app_window::framebufferSizeCallback(GLFWwindow* window, int window_width, int window_height) 103 | { 104 | // Triggers when the openGL window is resized 105 | app_window::window_width = window_width; 106 | app_window::window_height = window_height; 107 | 108 | int max_dim = window_width > window_height ? window_width : window_height; 109 | int x_offset = (max_dim - window_width) / 2; // Calculate x offset to center the viewport 110 | int y_offset = (max_dim - window_height) / 2; // Calculate y offset to center the viewport 111 | 112 | // Set the viewport to the maximum dimension and center it at (0, 0) 113 | glViewport(-x_offset, -y_offset, max_dim, max_dim); 114 | 115 | isWindowSizeChanging = true; 116 | // glViewport(0, 0, max_size, max_size); 117 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/app_window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "buffers/gBuffers.h" 6 | #include "geom_store.h" 7 | 8 | class app_window 9 | { 10 | public: 11 | bool is_glwindow_success = false; 12 | static int window_width; 13 | static int window_height; 14 | static bool isWindowSizeChanging; 15 | const char* log = ""; 16 | 17 | // Constructor and Destructor 18 | app_window(); 19 | ~app_window(); 20 | 21 | // Functions 22 | void init(); 23 | void app_render(); 24 | static void framebufferSizeCallback(GLFWwindow* window, int window_width, int window_height); 25 | private: 26 | GLFWwindow* window = nullptr; 27 | geom_store geom; 28 | }; 29 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/IndexBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "IndexBuffer.h" 2 | IndexBuffer::IndexBuffer() 3 | :ib_id(0),m_count(0) 4 | { 5 | // Empty constructor at program start 6 | } 7 | 8 | IndexBuffer::~IndexBuffer() 9 | { 10 | // Release the buffer ID 11 | glDeleteBuffers(1, &ib_id); 12 | } 13 | 14 | 15 | void IndexBuffer::createIndexBuffer(const unsigned int* indices, unsigned int count) 16 | { 17 | m_count = count; 18 | 19 | // Generate a new buffer ID for the index buffer 20 | glGenBuffers(1, &ib_id); 21 | 22 | // Bind the buffer to the GL_ELEMENT_ARRAY_BUFFER target 23 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib_id); 24 | 25 | // Copy the index data to the buffer 26 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), indices, GL_STATIC_DRAW); 27 | } 28 | 29 | void IndexBuffer::Bind() const 30 | { 31 | // Bind the buffer to the GL_ELEMENT_ARRAY_BUFFER target 32 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib_id); 33 | } 34 | 35 | void IndexBuffer::UnBind() const 36 | { 37 | // Unbind the buffer from the GL_ELEMENT_ARRAY_BUFFER target 38 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 39 | } 40 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/IndexBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | class IndexBuffer 7 | { 8 | public: 9 | IndexBuffer(); 10 | ~IndexBuffer(); 11 | void createIndexBuffer(const unsigned int* data, unsigned int count); 12 | void Bind() const; 13 | void UnBind() const; 14 | private: 15 | unsigned int ib_id; 16 | unsigned int m_count; 17 | }; 18 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/Texture.cpp: -------------------------------------------------------------------------------- 1 | #include "Texture.h" 2 | 3 | Texture::Texture() 4 | : texture_id(0), texture_filepath(""), local_buffer(nullptr), texture_width(0), texture_height(0), texture_bpp(0) 5 | { 6 | // Initialize texture data members 7 | } 8 | 9 | Texture::~Texture() 10 | { 11 | // Free the local buffer if it has been allocated 12 | if (local_buffer) 13 | stbi_image_free(local_buffer); 14 | 15 | // Delete the OpenGL texture if it has been created 16 | if (texture_id) 17 | glDeleteTextures(1, &texture_id); 18 | } 19 | 20 | void Texture::Bind(unsigned int slot) const 21 | { 22 | // Activate a texture slot 23 | glActiveTexture(GL_TEXTURE0 + slot); 24 | 25 | // Bind the texture to the slot 26 | glBindTexture(GL_TEXTURE_2D, texture_id); 27 | } 28 | 29 | void Texture::UnBind() 30 | { 31 | // Unbind the current texture 32 | glBindTexture(GL_TEXTURE_2D, 0); 33 | } 34 | 35 | void Texture::LoadTexture(const std::string& filepath) 36 | { 37 | int width, height, bpp; 38 | 39 | // Flip the texture file ?? 40 | // stbi_set_flip_vertically_on_load(1); 41 | 42 | // Load the texture from file using stb_image library 43 | local_buffer = stbi_load(filepath.c_str(), &width, &height, &bpp, 4); 44 | 45 | if (!local_buffer) 46 | { 47 | // Handle failure to load texture 48 | std::cout << "Failed to load texture: " << filepath << std::endl; 49 | } 50 | 51 | // Generate a new texture in OpenGL and bind it 52 | glGenTextures(1, &texture_id); 53 | glBindTexture(GL_TEXTURE_2D, texture_id); 54 | 55 | // Set texture parameters 56 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 57 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 58 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 59 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 60 | 61 | // Upload the texture data to OpenGL 62 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, local_buffer); 63 | 64 | // Unbind the texture 65 | glBindTexture(GL_TEXTURE_2D, 0); 66 | 67 | // Set the texture properties 68 | texture_filepath = filepath; 69 | texture_width = width; 70 | texture_height = height; 71 | texture_bpp = bpp; 72 | 73 | // Free the image data 74 | // stbi_image_free(local_buffer); 75 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/Texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../../lib/stb_image.h" 5 | #include 6 | 7 | class Texture 8 | { 9 | public: 10 | Texture(); 11 | ~Texture(); 12 | void LoadTexture(const std::string& filepath); 13 | void Bind(unsigned int slot = 0) const; 14 | void UnBind(); 15 | 16 | inline int GetWidth() const { return texture_width; } 17 | inline int GetHeight() const { return texture_height; } 18 | private: 19 | unsigned int texture_id; 20 | std::string texture_filepath; 21 | unsigned char* local_buffer; 22 | int texture_width, texture_height, texture_bpp; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/VertexArray.cpp: -------------------------------------------------------------------------------- 1 | #include "VertexArray.h" 2 | VertexArray::VertexArray() 3 | :va_id(0) 4 | { 5 | // Empty constructor at program start 6 | } 7 | 8 | VertexArray::~VertexArray() 9 | { 10 | // Destructor: deletes the vertex array object identified by the ID. 11 | glDeleteVertexArrays(1, &va_id); 12 | } 13 | 14 | 15 | void VertexArray::createVertexArray() 16 | { 17 | // Main Constructor: generates a unique vertex array object ID. 18 | glGenVertexArrays(1, &va_id); 19 | } 20 | 21 | void VertexArray::Bind() const 22 | { 23 | // Binds the vertex array object for use with subsequent OpenGL calls. 24 | glBindVertexArray(va_id); 25 | } 26 | 27 | void VertexArray::UnBind() const 28 | { 29 | // Unbinds the currently bound vertex array object. 30 | glBindVertexArray(0); 31 | } 32 | 33 | 34 | /* 35 | The function parameters are: 36 | VertexBuffer& vb: A reference to the vertex buffer object that contains the vertex data. 37 | Layout contains 38 | const int& index: The buffer index that this vertex attribute is associated with. 39 | const int& size: The number of components in the vertex attribute (e.g. 3 for xyz coordinates, 4 for rgba colors, etc.). 40 | const int& stride: The distance in bytes between consecutive vertices in the vertex buffer object. This is useful when the buffer contains interleaved vertex data (e.g. xyzrgba, xyznxynzrgba, etc.). 41 | const int& offset: The offset in bytes of the first component of the vertex attribute in the vertex buffer object 42 | */ 43 | void VertexArray::AddBuffer(const VertexBuffer& vbo, const VertexBufferLayout& layout) 44 | { 45 | // Associates a vertex buffer object with the vertex array object. 46 | // Bind the vertex array object. 47 | Bind(); 48 | 49 | // Bind the vertex buffer object. 50 | vbo.Bind(); 51 | 52 | const auto& elements = layout.GetElements(); 53 | unsigned int offset = 0; 54 | 55 | for (int i=0;i 3 | #include 4 | #include 5 | #include "VertexBuffer.h" 6 | #include "VertexArray.h" 7 | #include "VertexBufferLayout.h" 8 | 9 | class VertexArray 10 | { 11 | public: 12 | VertexArray(); 13 | ~VertexArray(); 14 | void createVertexArray(); 15 | void AddBuffer(const VertexBuffer& vbo, const VertexBufferLayout& layout); 16 | void Bind() const; 17 | void UnBind() const; 18 | private: 19 | unsigned int va_id; 20 | }; -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/VertexBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "VertexBuffer.h" 2 | VertexBuffer::VertexBuffer() 3 | :vb_id(0) 4 | { 5 | // Empty constructor at program start 6 | } 7 | 8 | VertexBuffer::~VertexBuffer() 9 | { 10 | // Destructor: deletes the vertex buffer object identified by the ID. 11 | glDeleteBuffers(1, &vb_id); 12 | } 13 | 14 | 15 | void VertexBuffer::createVertexBuffer(const void* data, unsigned int size) 16 | { 17 | // Main Constructor 18 | glGenBuffers(1, &vb_id); 19 | glBindBuffer(GL_ARRAY_BUFFER, vb_id); 20 | glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); 21 | } 22 | 23 | 24 | void VertexBuffer::Bind() const 25 | { 26 | // Bind this vertex buffer with its id 27 | glBindBuffer(GL_ARRAY_BUFFER, vb_id); 28 | } 29 | 30 | void VertexBuffer::UnBind() const 31 | { 32 | // Unbinds the currently bound vertex buffer object. 33 | glBindBuffer(GL_ARRAY_BUFFER, 0); 34 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/VertexBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | class VertexBuffer 7 | { 8 | public: 9 | VertexBuffer(); 10 | ~VertexBuffer(); 11 | void createVertexBuffer(const void* data, unsigned int size); 12 | void Bind() const; 13 | void UnBind() const; 14 | private: 15 | unsigned int vb_id; 16 | }; 17 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/VertexBufferLayout.cpp: -------------------------------------------------------------------------------- 1 | #include "VertexBufferLayout.h" 2 | 3 | VertexBufferLayout::VertexBufferLayout() 4 | : m_Stride(0) 5 | { 6 | // Constructor that initializes the stride to zero 7 | } 8 | 9 | // Specialized version of the Push() function for adding elements of type float 10 | void VertexBufferLayout::AddFloat(unsigned int count) 11 | { 12 | Push(GL_FLOAT, count, GL_FALSE); 13 | } 14 | 15 | // Specialized version of the Push() function for adding elements of type unsigned int 16 | void VertexBufferLayout::AddUnsignedInt(unsigned int count) 17 | { 18 | Push(GL_UNSIGNED_INT, count, GL_FALSE); 19 | } 20 | 21 | // Specialized version of the Push() function for adding elements of type unsigned char 22 | void VertexBufferLayout::AddUnsignedChar(unsigned int count) 23 | { 24 | Push(GL_UNSIGNED_BYTE, count, GL_TRUE); 25 | } 26 | 27 | 28 | void VertexBufferLayout::Push(unsigned int type, unsigned int count, unsigned char normalized) 29 | { 30 | m_Elements.push_back({ type, count, normalized });// Add a new element of type GL_FLOAT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE to the vector 31 | m_Stride += count * VertexBufferElement::GetSizeOfType(type); // Increase the stride by the size of the new element 32 | } 33 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/VertexBufferLayout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | // Thanks to The Cherno 8 | 9 | // This struct defines a single element in the vertex buffer layout 10 | struct VertexBufferElement 11 | { 12 | public: 13 | 14 | unsigned int type; // The data type of the element (e.g. GL_FLOAT) 15 | unsigned int count; // The number of elements of this type (e.g. 3 for a 3-component vector) 16 | unsigned char normalized; // Whether the dstruct VertexBufferLayout::VertexBufferElement 17 | 18 | static unsigned int GetSizeOfType(unsigned int type) 19 | { 20 | //This function returns the size of a single element of this type in bytes 21 | switch (type) 22 | { 23 | case GL_FLOAT: return 4; 24 | case GL_UNSIGNED_INT: return 4; 25 | case GL_UNSIGNED_BYTE: return 1; 26 | } 27 | assert(false); 28 | return 0; 29 | } 30 | private: 31 | 32 | }; 33 | 34 | class VertexBufferLayout 35 | { 36 | public: 37 | VertexBufferLayout(); 38 | 39 | // Specialized version of the Push() function for adding elements of type float 40 | void AddFloat(unsigned int count); 41 | 42 | // Specialized version of the Push() function for adding elements of type unsigned int 43 | void AddUnsignedInt(unsigned int count); 44 | 45 | // Specialized version of the Push() function for adding elements of type unsigned char 46 | void AddUnsignedChar(unsigned int count); 47 | 48 | // Getter function that returns the vector of vertex buffer elements 49 | inline const std::vector GetElements() const { return m_Elements; } 50 | 51 | // Getter function that returns the stride of the vertex buffer layout in bytes 52 | inline unsigned int GetStride() const { return m_Stride; } 53 | 54 | private: 55 | std::vector m_Elements; // The vector of vertex buffer elements 56 | unsigned int m_Stride; // The stride of the vertex buffer layout in bytes 57 | void Push(unsigned int type, unsigned int count, unsigned char normalized); 58 | }; -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/gBuffers.cpp: -------------------------------------------------------------------------------- 1 | #include "gBuffers.h" 2 | 3 | 4 | gBuffers::gBuffers() 5 | :vbo(),vao(),ibo() 6 | { 7 | // Empty constructor 8 | } 9 | 10 | gBuffers::~gBuffers() 11 | { 12 | // Destructor 13 | } 14 | 15 | void gBuffers::CreateBuffers(const void* vb_data, 16 | unsigned int& vb_size, 17 | const unsigned int* ib_indices, 18 | unsigned int& ib_count, 19 | VertexBufferLayout& vb_layout) 20 | { 21 | 22 | vao.createVertexArray(); 23 | 24 | // Vertex buffer (vertices and number of vertices * sizeof(float) 25 | vbo.createVertexBuffer(vb_data, vb_size); 26 | 27 | // Index buffer (indices and number of indices) 28 | ibo.createIndexBuffer(ib_indices, ib_count); 29 | 30 | // Vertex Array (vertex buffer and vertex buffer layout) 31 | vao.AddBuffer(vbo, vb_layout); 32 | } 33 | 34 | void gBuffers::Bind() const 35 | { 36 | // Bind the buffers 37 | vao.Bind(); 38 | ibo.Bind(); 39 | } 40 | 41 | 42 | void gBuffers::UnBind() const 43 | { 44 | // Un Bind the buffers 45 | vao.UnBind(); 46 | ibo.UnBind(); 47 | } 48 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/gBuffers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "VertexBuffer.h" 3 | #include "VertexArray.h" 4 | #include "IndexBuffer.h" 5 | #include "Texture.h" 6 | 7 | class gBuffers 8 | { 9 | public: 10 | gBuffers(); 11 | ~gBuffers(); 12 | void Bind()const; 13 | void UnBind()const; 14 | void CreateBuffers(const void* vb_data, 15 | unsigned int& vb_size, 16 | const unsigned int* ib_indices, 17 | unsigned int& ib_count, 18 | VertexBufferLayout& layout); 19 | VertexBuffer vbo; 20 | VertexArray vao; 21 | IndexBuffer ibo; 22 | private: 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /opengl_textrendering/src/buffers/junk.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | // Clear the previous map (if any) 4 | // Clear the previous map (if any) 5 | ch_atlas.clear(); 6 | 7 | // set the font size 8 | FT_Set_Pixel_Sizes(face, 0, 48); 9 | 10 | // initialize variables to keep track of texture atlas size 11 | int atlas_width = 0; 12 | int atlas_height = 0; 13 | 14 | // loop through the characters and load their glyphs 15 | for (unsigned char c = 0; c < 128; c++) 16 | { 17 | // load glyph 18 | if (FT_Load_Char(face, c, FT_LOAD_RENDER)) 19 | { 20 | std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; 21 | continue; 22 | } 23 | 24 | // update atlas size variables 25 | atlas_width += face->glyph->bitmap.width; 26 | atlas_height = std::max(atlas_height, static_cast(face->glyph->bitmap.rows)); 27 | } 28 | 29 | // generate texture for the atlas 30 | glGenTextures(1, &textureID); 31 | glBindTexture(GL_TEXTURE_2D, textureID); 32 | glTexImage2D( 33 | GL_TEXTURE_2D, 34 | 0, 35 | GL_RED, 36 | atlas_width, 37 | atlas_height, 38 | 0, 39 | GL_RED, 40 | GL_UNSIGNED_BYTE, 41 | nullptr 42 | ); 43 | 44 | // set texture options 45 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 46 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 47 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 48 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 49 | 50 | // initialize x position for next glyph 51 | int x = 0; 52 | 53 | // loop through the characters again and add their glyphs to the atlas 54 | for (unsigned char c = 0; c < 128; c++) 55 | { 56 | // load glyph 57 | if (FT_Load_Char(face, c, FT_LOAD_RENDER)) 58 | { 59 | std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; 60 | continue; 61 | } 62 | 63 | // add glyph to texture atlas 64 | glTexSubImage2D( 65 | GL_TEXTURE_2D, 66 | 0, 67 | x, 68 | 0, 69 | face->glyph->bitmap.width, 70 | face->glyph->bitmap.rows, 71 | GL_RED, 72 | GL_UNSIGNED_BYTE, 73 | face->glyph->bitmap.buffer 74 | ); 75 | 76 | // store glyph information in character map 77 | Character character = { 78 | textureID, 79 | glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), 80 | glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top), 81 | face->glyph->advance.x 82 | }; 83 | ch_atlas.insert(std::pair(c, character)); 84 | 85 | // update x position for next glyph 86 | x += face->glyph->bitmap.width; 87 | 88 | 89 | } 90 | 91 | */ 92 | 93 | 94 | 95 | /* 96 | 97 | // Clear the previous map (if any) 98 | ch_atlas.clear(); 99 | 100 | // set the font size 101 | FT_Set_Pixel_Sizes(face, 0, 48); 102 | 103 | // initialize variables to keep track of texture atlas size 104 | int atlas_width = 0; 105 | int atlas_height = 0; 106 | 107 | 108 | // loop through the characters and load their glyphs 109 | for (unsigned char c = 0; c < 128; c++) 110 | { 111 | // load glyph 112 | if (FT_Load_Char(face, c, FT_LOAD_RENDER)) 113 | { 114 | std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; 115 | continue; 116 | } 117 | 118 | // generate texture for glyph 119 | glGenTextures(1, &textureID); 120 | glBindTexture(GL_TEXTURE_2D, textureID); 121 | glTexImage2D( 122 | GL_TEXTURE_2D, 123 | 0, 124 | GL_RED, 125 | face->glyph->bitmap.width, 126 | face->glyph->bitmap.rows, 127 | 0, 128 | GL_RED, 129 | GL_UNSIGNED_BYTE, 130 | face->glyph->bitmap.buffer 131 | ); 132 | // set texture options 133 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 134 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 135 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 136 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 137 | 138 | // update atlas size variables 139 | atlas_width += face->glyph->bitmap.width; 140 | atlas_height = std::max(atlas_height, static_cast(face->glyph->bitmap.rows)); 141 | 142 | 143 | // store character for later use 144 | Character character = { 145 | glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), 146 | glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top), 147 | (unsigned int)face->glyph->advance.x, 148 | glm::vec2(0), 149 | glm::vec2(0), 150 | glm::vec2(0), 151 | glm::vec2(0) 152 | }; 153 | ch_atlas.insert(std::pair(c, character)); 154 | } 155 | 156 | // Update the texture dimensions 157 | TextureWidth = atlas_width; 158 | TextureHeight = atlas_height; 159 | 160 | // compute texture coordinates for each character 161 | float x = 0; 162 | float y = 0; 163 | for (auto& ch : ch_atlas) 164 | { 165 | Character& character = ch.second; 166 | 167 | // compute glyph texture coordinates 168 | character.top_left.x = x / atlas_width; 169 | character.top_left.y = y / atlas_height; 170 | character.bot_right.x = (x + character.Size.x) / atlas_width; 171 | character.bot_right.y = (y + character.Size.y) / atlas_height; 172 | 173 | // update x position for next glyph 174 | x += character.Size.x; 175 | } 176 | 177 | // compute normalized texture coordinates for whitespace character 178 | Character& space_char = ch_atlas[' ']; 179 | space_char.top_left.x = 0.0f; 180 | space_char.top_left.y = 0.0f; 181 | space_char.bot_right.x = space_char.Size.x / atlas_width; 182 | space_char.bot_right.y = space_char.Size.y / atlas_height; 183 | 184 | // compute normalized texture coordinates for newline character 185 | Character& newline_char = ch_atlas['\n']; 186 | newline_char.top_left.x = 0.0f; 187 | newline_char.top_left.y = 0.0f; 188 | newline_char.bot_right.x = 0.0f; 189 | newline_char.bot_right.y = 0.0f; 190 | 191 | */ 192 | 193 | 194 | 195 | 196 | /* 197 | 198 | // set size to load glyphs as 199 | FT_Set_Pixel_Sizes(face, 0, 48); 200 | 201 | // disable byte-alignment restriction 202 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 203 | 204 | // generate texture atlas 205 | // GLuint texture; 206 | glGenTextures(1, &label_textureID); 207 | glBindTexture(GL_TEXTURE_2D, label_textureID); 208 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 1024, 1024, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); 209 | 210 | // set texture options 211 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 212 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 213 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 214 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 215 | 216 | // initialize atlas variables 217 | int x = 0; 218 | int y = 0; 219 | int max_height = 0; 220 | 221 | // loop through all printable ASCII characters 222 | for (unsigned char c = 32; c < 128; c++) 223 | { 224 | // load character glyph 225 | if (FT_Load_Char(face, c, FT_LOAD_RENDER)) 226 | { 227 | continue; 228 | } 229 | 230 | // store character data in struct 231 | Character character = 232 | { 233 | 0, 234 | glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), 235 | glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top), 236 | face->glyph->advance.x, 237 | glm::vec4(x, y + face->glyph->bitmap.rows - face->glyph->bitmap_top, 238 | face->glyph->bitmap.width, 239 | -1.0f*face->glyph->bitmap.rows) 240 | }; 241 | 242 | // add character to map 243 | ch_characters.insert(std::pair(c, character)); 244 | 245 | // update atlas variables 246 | x += face->glyph->bitmap.width + 1; 247 | max_height = std::max(max_height, int(face->glyph->bitmap.rows)); 248 | 249 | if (x >= 1024) 250 | { 251 | x = 0; 252 | y += max_height + 1; 253 | max_height = 0; 254 | } 255 | 256 | // update texture with glyph data 257 | glTexSubImage2D(GL_TEXTURE_2D, 258 | 0, 259 | character.TextureCoords.x, 260 | character.TextureCoords.y, 261 | character.TextureCoords.z, 262 | character.TextureCoords.w, 263 | GL_RED, 264 | GL_UNSIGNED_BYTE, 265 | face->glyph->bitmap.buffer); 266 | } 267 | 268 | 269 | */ 270 | 271 | 272 | /* 273 | 274 | 275 | label_store::label_store() 276 | :label_char_list(), label_loc(0), text_color(0), text_angle(0.0f), font_size(0.0f), char_count(0) 277 | { 278 | // Constructor 279 | // Stores individual line 280 | } 281 | 282 | label_store::~label_store() 283 | { 284 | 285 | } 286 | 287 | void label_store::add_label(const char* label, glm::vec2 label_loc, float text_angle, float font_size) 288 | { 289 | // Add the label 290 | unsigned int char_location = 0; 291 | 292 | for (const char* c = label; *c != '\0'; c++) 293 | { 294 | //Character ch; 295 | //ch.this_char = *c; // store the character 296 | //ch.texture_id =0; // Set texture id 0 297 | //ch.char_location = char_location; 298 | label_char_list.insert(std::make_pair(char_location, *c)); 299 | 300 | // Iterate the location 301 | char_location++; 302 | } 303 | 304 | this->char_count = char_location; 305 | this->label_loc = label_loc; 306 | this->text_angle = text_angle; 307 | this->font_size = font_size; 308 | } 309 | 310 | void label_store::get_buffer(float* label_vertices, unsigned int* label_indices, 311 | unsigned int& label_vertices_count, unsigned int& label_indices_count, std::map& char_atlas) 312 | { 313 | float x_val = label_loc.x; 314 | float y_val = label_loc.y; 315 | 316 | // return the buffer of each character (<> font size = 0.04f, <> font gap = 0.01f) 317 | for (auto& char_s : label_char_list) 318 | { 319 | 320 | Character ch = char_atlas[char_s.second]; 321 | font_size = 0.002f; 322 | 323 | float xpos = x_val + (ch.Bearing.x * font_size); 324 | float ypos = y_val - (ch.Size.y - ch.Bearing.y) * font_size; 325 | 326 | float w = ch.Size.x * font_size; 327 | float h = ch.Size.y * font_size; 328 | 329 | glm::vec4 texture_scaled = ch.TextureCoords / font_size; 330 | 331 | // X Y coordinates 332 | // Point 1 333 | // Vertices [0,0] // 0th point 334 | label_vertices[label_vertices_count + 0] = xpos; 335 | label_vertices[label_vertices_count + 1] = ypos + h; 336 | 337 | // Label origin 338 | label_vertices[label_vertices_count + 2] = label_loc.x; 339 | label_vertices[label_vertices_count + 3] = label_loc.y; 340 | 341 | // Texture Glyph coordinate 342 | label_vertices[label_vertices_count + 4] = texture_scaled.x; 343 | label_vertices[label_vertices_count + 5] = texture_scaled.y; 344 | 345 | // Iterate 346 | label_vertices_count = label_vertices_count + 6; 347 | 348 | //__________________________________________________________________________________________ 349 | // Point 2 350 | // Vertices [0,1] // 1th point 351 | label_vertices[label_vertices_count + 0] = xpos; 352 | label_vertices[label_vertices_count + 1] = ypos; 353 | 354 | // Font origin 355 | label_vertices[label_vertices_count + 2] = label_loc.x; 356 | label_vertices[label_vertices_count + 3] = label_loc.y; 357 | 358 | // Texture Glyph coordinate 359 | label_vertices[label_vertices_count + 4] = texture_scaled.x; 360 | label_vertices[label_vertices_count + 5] = texture_scaled.y + texture_scaled.w; 361 | 362 | // Iterate 363 | label_vertices_count = label_vertices_count + 6; 364 | 365 | //__________________________________________________________________________________________ 366 | // Point 3 367 | // Vertices [1,1] // 3th point 368 | label_vertices[label_vertices_count + 0] = xpos + w; 369 | label_vertices[label_vertices_count + 1] = ypos; 370 | 371 | // Font origin 372 | label_vertices[label_vertices_count + 2] = label_loc.x; 373 | label_vertices[label_vertices_count + 3] = label_loc.y; 374 | 375 | // Texture Glyph coordinate 376 | label_vertices[label_vertices_count + 4] = texture_scaled.x + texture_scaled.z; 377 | label_vertices[label_vertices_count + 5] = texture_scaled.y + texture_scaled.w; 378 | 379 | // Iterate 380 | label_vertices_count = label_vertices_count + 6; 381 | 382 | //__________________________________________________________________________________________ 383 | // Point 4 384 | // Vertices [1,0] // 4th point 385 | label_vertices[label_vertices_count + 0] = xpos + w; 386 | label_vertices[label_vertices_count + 1] = ypos + h; 387 | 388 | // Font origin 389 | label_vertices[label_vertices_count + 2] = label_loc.x; 390 | label_vertices[label_vertices_count + 3] = label_loc.y; 391 | 392 | // Texture Glyph coordinate 393 | label_vertices[label_vertices_count + 4] = texture_scaled.x + texture_scaled.z; 394 | label_vertices[label_vertices_count + 5] = texture_scaled.y; 395 | 396 | // Iterate 397 | label_vertices_count = label_vertices_count + 6; 398 | 399 | x_val += (ch.Advance >> 6) * font_size; 400 | 401 | //__________________________________________________________________________________________ 402 | 403 | // Fix the index buffers 404 | // Set the node indices 405 | unsigned int t_id = ((label_indices_count / 6) * 4); 406 | // Triangle 0,1,2 407 | label_indices[label_indices_count + 0] = t_id + 0; 408 | label_indices[label_indices_count + 1] = t_id + 1; 409 | label_indices[label_indices_count + 2] = t_id + 2; 410 | 411 | // Triangle 2,3,0 412 | label_indices[label_indices_count + 3] = t_id + 2; 413 | label_indices[label_indices_count + 4] = t_id + 3; 414 | label_indices[label_indices_count + 5] = t_id + 0; 415 | 416 | // Increment 417 | label_indices_count = label_indices_count + 6; 418 | } 419 | } 420 | 421 | 422 | void label_store::get_buffer1(float* label_vertices, unsigned int* label_indices, 423 | unsigned int& label_vertices_count, unsigned int& label_indices_count, std::map& char_atlas) 424 | { 425 | //const float char_gap = font_size * 0.25f; 426 | //glm::vec2 temp_pt; 427 | //glm::vec2 char_pt; 428 | float x_val = label_loc.x; 429 | float y_val = label_loc.y; 430 | 431 | // return the buffer of each character (<> font size = 0.04f, <> font gap = 0.01f) 432 | for (auto& char_s : label_char_list) 433 | { 434 | 435 | Character ch = char_atlas[char_s.second]; 436 | font_size =0.002f; 437 | 438 | float xpos = x_val +(ch.Bearing.x * font_size); 439 | float ypos = y_val -(ch.Size.y - ch.Bearing.y) * font_size; 440 | 441 | float w = ch.Size.x *font_size; 442 | float h = ch.Size.y *font_size; 443 | 444 | 445 | // X Y coordinates 446 | // Point 1 447 | // Vertices [0,0] // 0th point 448 | label_vertices[label_vertices_count + 0] = xpos; 449 | label_vertices[label_vertices_count + 1] = ypos+h; 450 | 451 | // Label origin 452 | label_vertices[label_vertices_count + 2] = label_loc.x; 453 | label_vertices[label_vertices_count + 3] = label_loc.y; 454 | 455 | // Texture Glyph coordinate 456 | label_vertices[label_vertices_count + 4] = 0; 457 | label_vertices[label_vertices_count + 5] = 0; 458 | 459 | // Iterate 460 | label_vertices_count = label_vertices_count + 6; 461 | 462 | //__________________________________________________________________________________________ 463 | // Point 2 464 | // Vertices [0,1] // 1th point 465 | label_vertices[label_vertices_count + 0] = xpos; 466 | label_vertices[label_vertices_count + 1] = ypos; 467 | 468 | // Font origin 469 | label_vertices[label_vertices_count + 2] = label_loc.x; 470 | label_vertices[label_vertices_count + 3] = label_loc.y; 471 | 472 | // Texture Glyph coordinate 473 | label_vertices[label_vertices_count + 4] = 0; 474 | label_vertices[label_vertices_count + 5] = 1; 475 | 476 | // Iterate 477 | label_vertices_count = label_vertices_count + 6; 478 | 479 | //__________________________________________________________________________________________ 480 | // Point 3 481 | // Vertices [1,1] // 3th point 482 | label_vertices[label_vertices_count + 0] = xpos+w; 483 | label_vertices[label_vertices_count + 1] = ypos; 484 | 485 | // Font origin 486 | label_vertices[label_vertices_count + 2] = label_loc.x; 487 | label_vertices[label_vertices_count + 3] = label_loc.y; 488 | 489 | // Texture Glyph coordinate 490 | label_vertices[label_vertices_count + 4] = 1; 491 | label_vertices[label_vertices_count + 5] = 1; 492 | 493 | // Iterate 494 | label_vertices_count = label_vertices_count + 6; 495 | 496 | //__________________________________________________________________________________________ 497 | // Point 4 498 | // Vertices [1,0] // 4th point 499 | label_vertices[label_vertices_count + 0] = xpos+w; 500 | label_vertices[label_vertices_count + 1] = ypos+h; 501 | 502 | // Font origin 503 | label_vertices[label_vertices_count + 2] = label_loc.x; 504 | label_vertices[label_vertices_count + 3] = label_loc.y; 505 | 506 | // Texture Glyph coordinate 507 | label_vertices[label_vertices_count + 4] = 1; 508 | label_vertices[label_vertices_count + 5] = 0; 509 | 510 | // Iterate 511 | label_vertices_count = label_vertices_count + 6; 512 | 513 | x_val += (ch.Advance >> 6) * font_size; 514 | 515 | //__________________________________________________________________________________________ 516 | 517 | // Fix the index buffers 518 | // Set the node indices 519 | unsigned int t_id = ((label_indices_count / 6) * 4); 520 | // Triangle 0,1,2 521 | label_indices[label_indices_count + 0] = t_id + 0; 522 | label_indices[label_indices_count + 1] = t_id + 1; 523 | label_indices[label_indices_count + 2] = t_id + 2; 524 | 525 | // Triangle 2,3,0 526 | label_indices[label_indices_count + 3] = t_id + 2; 527 | label_indices[label_indices_count + 4] = t_id + 3; 528 | label_indices[label_indices_count + 5] = t_id + 0; 529 | 530 | // Increment 531 | label_indices_count = label_indices_count + 6; 532 | } 533 | } 534 | 535 | glm::vec2 label_store::rotate_pt(glm::vec2& rotate_about, glm::vec2 pt, float& rotation_angle) 536 | { 537 | // Return the rotation point 538 | glm::vec2 translated_pt = pt - rotate_about; 539 | 540 | // Apply rotation 541 | float radians = (rotation_angle);// * 3.14159365f) / 180.0f; // convert degrees to radians 542 | float cos_theta = cos(radians); 543 | float sin_theta = sin(radians); 544 | 545 | // Rotated point of the corners 546 | glm::vec2 rotated_pt = glm::vec2((translated_pt.x * cos_theta) - (translated_pt.y * sin_theta), 547 | (translated_pt.x * sin_theta) + (translated_pt.y * cos_theta)); 548 | 549 | return (rotated_pt + rotate_about); 550 | } 551 | 552 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 553 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 554 | 555 | 556 | 557 | */ -------------------------------------------------------------------------------- /opengl_textrendering/src/font_atlas.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "font_atlas.h" 3 | 4 | font_atlas::font_atlas() 5 | :textureID(0), TextureWidth(0), TextureHeight(0) 6 | { 7 | 8 | } 9 | 10 | font_atlas::~font_atlas() 11 | { 12 | } 13 | 14 | void font_atlas::create_atlas() 15 | { 16 | // FreeType 17 | // -------- 18 | FT_Library ft; 19 | // All functions return a value different than 0 whenever an error occurred 20 | if (FT_Init_FreeType(&ft)) 21 | { 22 | std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl; 23 | return; 24 | } 25 | 26 | // load font as face 27 | FT_Face face; 28 | if (FT_New_Face(ft, "src/shaders/ttf_CenturyGothic.ttf", 0, &face)) { 29 | std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl; 30 | return; 31 | } 32 | else 33 | { 34 | // Clear the previous map (if any) 35 | ch_atlas.clear(); 36 | 37 | // set the font size 38 | FT_Set_Pixel_Sizes(face, 0, 128); 39 | 40 | // Below line keep the unpack alignment otherwise fonts will be skewed 41 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 42 | 43 | // initialize variables to keep track of texture atlas size 44 | int atlas_width = 0; 45 | int atlas_height = 0; 46 | 47 | // loop through the characters and load their glyphs 48 | for (unsigned char c = 0; c < 128; c++) 49 | { 50 | // load glyph 51 | if (FT_Load_Char(face, c, FT_LOAD_RENDER)) 52 | { 53 | std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; 54 | continue; 55 | } 56 | 57 | // update atlas size variables 58 | atlas_width += face->glyph->bitmap.width; 59 | atlas_height = std::max(atlas_height, static_cast(face->glyph->bitmap.rows)); 60 | } 61 | 62 | // generate texture for the atlas 63 | glGenTextures(1, &textureID); 64 | glBindTexture(GL_TEXTURE_2D, textureID); 65 | glTexImage2D( 66 | GL_TEXTURE_2D, 67 | 0, 68 | GL_RED, 69 | atlas_width, 70 | atlas_height, 71 | 0, 72 | GL_RED, 73 | GL_UNSIGNED_BYTE, 74 | nullptr 75 | ); 76 | 77 | // set texture options 78 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 79 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 80 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 81 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 82 | 83 | // initialize x position for next glyph 84 | int x = 0; 85 | 86 | // loop through the characters again and add their glyphs to the atlas 87 | for (unsigned char c = 0; c < 128; c++) 88 | { 89 | // load glyph 90 | if (FT_Load_Char(face, static_cast(c), FT_LOAD_RENDER)) 91 | { 92 | std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; 93 | continue; 94 | } 95 | 96 | // add glyph to texture atlas 97 | /* glTexSubImage2D( 98 | GL_TEXTURE_2D, 99 | 0, 100 | x, 101 | 0, 102 | face->glyph->bitmap.width, 103 | face->glyph->bitmap.rows, 104 | GL_RED, 105 | GL_UNSIGNED_BYTE, 106 | face->glyph->bitmap.buffer 107 | );*/ 108 | 109 | glTextureSubImage2D( 110 | textureID, 111 | 0, 112 | x, 113 | 0, 114 | face->glyph->bitmap.width, 115 | face->glyph->bitmap.rows, 116 | GL_RED, 117 | GL_UNSIGNED_BYTE, 118 | face->glyph->bitmap.buffer 119 | ); 120 | 121 | // store glyph information in character map 122 | Character character; 123 | 124 | character.Size = glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows); 125 | character.Bearing = glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top); 126 | character.Advance = face->glyph->advance.x; 127 | 128 | // compute glyph texture coordinates 129 | character.top_left.x = static_cast(x) / static_cast(atlas_width); 130 | character.top_left.y = 0.0f; 131 | character.bot_right.x = static_cast(x + character.Size.x) / static_cast(atlas_width); 132 | character.bot_right.y = static_cast(character.Size.y) / static_cast(atlas_height); 133 | 134 | ch_atlas.insert(std::pair(c, character)); 135 | 136 | // update x position for next glyph 137 | x += face->glyph->bitmap.width; 138 | } 139 | } 140 | 141 | // destroy FreeType once we're finished 142 | FT_Done_Face(face); 143 | FT_Done_FreeType(ft); 144 | } 145 | -------------------------------------------------------------------------------- /opengl_textrendering/src/font_atlas.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "buffers/gBuffers.h" 12 | #include 13 | 14 | // FreeType 15 | #include 16 | #include FT_FREETYPE_H 17 | 18 | /// Holds all state information relevant to a character as loaded using FreeType 19 | struct Character 20 | { 21 | glm::ivec2 Size; // Size of glyph (width & height) 22 | glm::ivec2 Bearing; // Offset from baseline to left/top of glyph 23 | 24 | // note that advance is number of 1/64 pixels) 25 | // (ch.Advance >> 6) // bitshift by 6 to get value in pixels (2^6 = 64) 26 | unsigned int Advance; // Horizontal offset to advance to next glyph 27 | 28 | glm::vec2 top_left; // location of this character in the atlas - top left [0,0] 29 | glm::vec2 bot_right; // location of this character in the atlas - bot right [1,1] 30 | }; 31 | 32 | class font_atlas 33 | { 34 | public: 35 | unsigned int textureID; 36 | unsigned int TextureWidth; // Total width of the atlas 37 | unsigned int TextureHeight; // Total height of the atlas 38 | std::map ch_atlas; 39 | 40 | font_atlas(); 41 | ~font_atlas(); 42 | void create_atlas(); // Function to create the atlas 43 | void Bind_atlas(); 44 | void UnBind_atlas(); 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /opengl_textrendering/src/geom_store.cpp: -------------------------------------------------------------------------------- 1 | #include "geom_store.h" 2 | 3 | geom_store::geom_store() 4 | { 5 | } 6 | 7 | geom_store::~geom_store() 8 | { 9 | } 10 | 11 | void geom_store::set_geometry() 12 | { 13 | // Set the geometry 14 | unsigned int node_vertices_count = 6 * 3; 15 | float* node_vertices = new float[node_vertices_count]; 16 | 17 | unsigned int node_indices_count = 3; 18 | unsigned int* node_indices = new unsigned int[node_indices_count]; 19 | 20 | unsigned int node_vertex_index = 0; 21 | unsigned int node_indices_index = 0; 22 | 23 | set_simple_triangle(node_vertices, node_vertex_index, node_indices, node_indices_index); 24 | 25 | VertexBufferLayout vb_tri; 26 | vb_tri.AddFloat(3); 27 | vb_tri.AddFloat(3); 28 | 29 | // Create the buffers 30 | unsigned int node_vertices_size = node_vertices_count * sizeof(float); 31 | tri_buffers.CreateBuffers(node_vertices, node_vertices_size, node_indices, node_indices_count, vb_tri); 32 | 33 | // Create the shader 34 | tri_shader.create_shader("src/shaders/basic_vert_shader.vert", "src/shaders/basic_frag_shader.frag"); 35 | 36 | // Shader for the text 37 | text_shader.create_shader("src/shaders/text_vert_shader.vert", "src/shaders/text_frag_shader.frag"); 38 | text_shader.setUniform("zoomscale", 1.0f); 39 | text_shader.setUniform("u_Texture", 0); 40 | 41 | // Add the labels 42 | all_labels.init(); 43 | all_labels.add_text("Length = 98.76532101", glm::vec2(-0.8, -0.3), glm::vec3(1.0f, 1.0f, 0.0f), 1.0f, 45, 0.0004f); 44 | all_labels.add_text("Pulled Pork Sandwich!!", glm::vec2(-0.4, 0), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, -15, 0.0003f); 45 | all_labels.add_text("Hello@", glm::vec2(-0.8, 0.3), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, 5.0f, 0.0003f); 46 | 47 | // all_labels.add_text("C", glm::vec2(-0.8, -0.6), glm::vec3(1.0f, 1.0f, 1.0f), 1.0f, 0, 0.04f, 0, 0); 48 | all_labels.set_buffers(); 49 | 50 | } 51 | 52 | 53 | void geom_store::set_simple_triangle(float* vertices, unsigned int& vertices_index, 54 | unsigned int* indices, unsigned int& indices_index) 55 | { 56 | 57 | // Point 1 58 | vertices[vertices_index + 0] = -0.5; 59 | vertices[vertices_index + 1] = -0.5; 60 | vertices[vertices_index + 2] = 0.0f; 61 | 62 | vertices[vertices_index + 3] = 1.0f; 63 | vertices[vertices_index + 4] = 1.0f; 64 | vertices[vertices_index + 5] = 1.0f; 65 | 66 | vertices_index = vertices_index + 6; 67 | 68 | // Point 2 69 | vertices[vertices_index + 0] = 0.5; 70 | vertices[vertices_index + 1] = -0.5; 71 | vertices[vertices_index + 2] = 0.0f; 72 | 73 | vertices[vertices_index + 3] = 1.0f; 74 | vertices[vertices_index + 4] = 1.0f; 75 | vertices[vertices_index + 5] = 1.0f; 76 | 77 | vertices_index = vertices_index + 6; 78 | 79 | // Point 3 80 | vertices[vertices_index + 0] = 0.0; 81 | vertices[vertices_index + 1] = 0.5; 82 | vertices[vertices_index + 2] = 0.0f; 83 | 84 | vertices[vertices_index + 3] = 1.0f; 85 | vertices[vertices_index + 4] = 1.0f; 86 | vertices[vertices_index + 5] = 1.0f; 87 | 88 | vertices_index = vertices_index + 6; 89 | 90 | 91 | // Set the indices 92 | indices[indices_index + 0] = 0; 93 | indices[indices_index + 1] = 1; 94 | indices[indices_index + 2] = 2; 95 | } 96 | 97 | void geom_store::paint_geometry() 98 | { 99 | // Paint the Triangle 100 | //tri_shader.Bind(); 101 | //tri_buffers.Bind(); 102 | 103 | //// glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); 104 | 105 | //tri_buffers.UnBind(); 106 | //tri_shader.UnBind(); 107 | 108 | 109 | // Paint the Text 110 | text_shader.Bind(); 111 | all_labels.paint_text(); 112 | text_shader.UnBind(); 113 | } 114 | 115 | 116 | -------------------------------------------------------------------------------- /opengl_textrendering/src/geom_store.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "buffers/gBuffers.h" 3 | #include "shaders/shader.h" 4 | #include "label_text_store.h" 5 | 6 | class geom_store 7 | { 8 | public: 9 | 10 | geom_store(); 11 | ~geom_store(); 12 | void set_geometry(); 13 | void paint_geometry(); 14 | private: 15 | void set_simple_triangle(float* vertices, unsigned int& vertices_count, 16 | unsigned int* indices, unsigned int& indices_count); 17 | gBuffers tri_buffers; 18 | label_text_store all_labels; 19 | 20 | shader tri_shader; 21 | shader text_shader; 22 | }; 23 | -------------------------------------------------------------------------------- /opengl_textrendering/src/label_text_store.cpp: -------------------------------------------------------------------------------- 1 | #include "label_text_store.h" 2 | 3 | 4 | label_text_store::label_text_store() 5 | :total_char_count(0) 6 | { 7 | // Constructor 8 | } 9 | 10 | label_text_store::~label_text_store() 11 | { 12 | // Destructor 13 | } 14 | 15 | void label_text_store::init() 16 | { 17 | // Clear all the label 18 | main_font.create_atlas(); 19 | total_char_count = 0; 20 | 21 | ////Check the values of the atlas 22 | //for (auto& atlas : main_font.ch_atlas) 23 | //{ 24 | // char ch = atlas.first; 25 | // Character ch_val = atlas.second; 26 | 27 | // std::cout << ch << "= (" 28 | // << ch_val.Bearing.x << ", " << ch_val.Bearing.y << ") (" 29 | // << ch_val.Size.x << ", " << ch_val.Size.y << ") " 30 | // << ch_val.Advance << " (" 31 | // << ch_val.top_left.x << ", " << ch_val.top_left.y << ") (" 32 | // << ch_val.bot_right.x << ", " << ch_val.bot_right.y << ")"<< std::endl; 33 | //} 34 | } 35 | 36 | void label_text_store::add_text(const char* label, glm::vec2 label_loc, glm::vec3 label_color, 37 | float geom_scale, float label_angle, float font_size) 38 | { 39 | // Create a temporary element 40 | label_text temp_label; 41 | temp_label.label = label; 42 | temp_label.label_loc = label_loc; 43 | temp_label.label_color = label_color; 44 | temp_label.label_angle = label_angle; 45 | temp_label.label_size = font_size; 46 | 47 | // Reserve space for the new element 48 | labels.reserve(labels.size() + 1); 49 | 50 | // Add to the list 51 | labels.push_back(temp_label); 52 | 53 | // Add to the char_count 54 | total_char_count = total_char_count + strlen(label); 55 | } 56 | 57 | void label_text_store::set_buffers() 58 | { 59 | 60 | // Define the label vertices of the model (4 vertex (to form a triangle) 2 position, 2 origin, 2 texture coordinate, 1 char ID) 61 | unsigned int label_vertex_count = 4 * 6 * total_char_count; 62 | float* label_vertices = new float[label_vertex_count]; 63 | 64 | // 6 indices to form a triangle 65 | unsigned int label_indices_count = 6 * total_char_count; 66 | unsigned int* label_indices = new unsigned int[label_indices_count]; 67 | 68 | unsigned int label_v_index = 0; 69 | unsigned int label_i_index = 0; 70 | 71 | for (auto& lb : labels) 72 | { 73 | // Fill the buffers for every individual character 74 | get_buffer(lb, label_vertices, label_v_index, label_indices, label_i_index); 75 | } 76 | 77 | // Create a layout 78 | VertexBufferLayout label_layout; 79 | label_layout.AddFloat(2); // Position 80 | label_layout.AddFloat(2); // Origin 81 | label_layout.AddFloat(2); // Texture coordinate 82 | 83 | unsigned int label_vertex_size = label_vertex_count * sizeof(float); 84 | 85 | // Create the buffers 86 | label_buffers.CreateBuffers((void*)label_vertices, label_vertex_size, 87 | (unsigned int*)label_indices, label_indices_count, label_layout); 88 | 89 | // Delete the dynamic array (From heap) 90 | delete[] label_vertices; 91 | delete[] label_indices; 92 | } 93 | 94 | void label_text_store::paint_text() 95 | { 96 | // Paint all the labels 97 | label_buffers.Bind(); 98 | 99 | glActiveTexture(GL_TEXTURE0); 100 | //// Bind the texture to the slot 101 | glBindTexture(GL_TEXTURE_2D, main_font.textureID); 102 | 103 | glDrawElements(GL_TRIANGLES, 6 * total_char_count, GL_UNSIGNED_INT, 0); 104 | 105 | glBindTexture(GL_TEXTURE_2D, 0); 106 | 107 | label_buffers.UnBind(); 108 | } 109 | 110 | 111 | void label_text_store::get_buffer(label_text& lb, 112 | float* vertices, unsigned int& vertex_index, unsigned int* indices, unsigned int& indices_index) 113 | { 114 | // Store the x,y location 115 | glm::vec2 loc = lb.label_loc; 116 | float x = loc.x; 117 | float y = loc.y; 118 | float scale =lb.label_size; 119 | glm::vec2 rotated_pt; 120 | 121 | for (int i = 0; lb.label[i] != '\0'; ++i) 122 | { 123 | // get the atlas information 124 | char ch = lb.label[i]; 125 | 126 | Character ch_data = main_font.ch_atlas[ch]; 127 | 128 | float xpos = x + (ch_data.Bearing.x * scale); 129 | float ypos = y - (ch_data.Size.y - ch_data.Bearing.y) * scale; 130 | 131 | float w = ch_data.Size.x * scale; 132 | float h = ch_data.Size.y * scale; 133 | 134 | float margin = 0.00002; // This value prevents the minor overlap with the next char when rendering 135 | 136 | // Point 1 137 | // Vertices [0,0] // 0th point 138 | rotated_pt = rotate_pt(loc, glm::vec2(xpos, ypos + h), lb.label_angle); 139 | 140 | vertices[vertex_index + 0] = rotated_pt.x; 141 | vertices[vertex_index + 1] = rotated_pt.y; 142 | 143 | // Label origin 144 | vertices[vertex_index + 2] = loc.x; 145 | vertices[vertex_index + 3] = loc.y; 146 | 147 | // Texture Glyph coordinate 148 | vertices[vertex_index + 4] = ch_data.top_left.x + margin; 149 | vertices[vertex_index + 5] = ch_data.top_left.y; 150 | 151 | // Iterate 152 | vertex_index = vertex_index + 6; 153 | 154 | //__________________________________________________________________________________________ 155 | 156 | // Point 2 157 | // Vertices [0,1] // 1th point 158 | rotated_pt = rotate_pt(loc, glm::vec2(xpos, ypos), lb.label_angle); 159 | 160 | vertices[vertex_index + 0] = rotated_pt.x; 161 | vertices[vertex_index + 1] = rotated_pt.y; 162 | 163 | // Label origin 164 | vertices[vertex_index + 2] = loc.x; 165 | vertices[vertex_index + 3] = loc.y; 166 | 167 | // Texture Glyph coordinate 168 | vertices[vertex_index + 4] = ch_data.top_left.x+ margin; 169 | vertices[vertex_index + 5] = ch_data.bot_right.y; 170 | 171 | // Iterate 172 | vertex_index = vertex_index + 6; 173 | 174 | //__________________________________________________________________________________________ 175 | 176 | // Point 3 177 | // Vertices [1,1] // 2th point 178 | rotated_pt = rotate_pt(loc, glm::vec2(xpos+w, ypos), lb.label_angle); 179 | 180 | vertices[vertex_index + 0] = rotated_pt.x; 181 | vertices[vertex_index + 1] = rotated_pt.y; 182 | 183 | // Label origin 184 | vertices[vertex_index + 2] = loc.x; 185 | vertices[vertex_index + 3] = loc.y; 186 | 187 | // Texture Glyph coordinate 188 | vertices[vertex_index + 4] = ch_data.bot_right.x - margin; 189 | vertices[vertex_index + 5] = ch_data.bot_right.y; 190 | 191 | // Iterate 192 | vertex_index = vertex_index + 6; 193 | 194 | //__________________________________________________________________________________________ 195 | 196 | // Point 4 197 | // Vertices [1,0] // 3th point 198 | rotated_pt = rotate_pt(loc, glm::vec2(xpos + w, ypos+h), lb.label_angle); 199 | 200 | vertices[vertex_index + 0] = rotated_pt.x; 201 | vertices[vertex_index + 1] = rotated_pt.y; 202 | 203 | // Label origin 204 | vertices[vertex_index + 2] = loc.x; 205 | vertices[vertex_index + 3] = loc.y; 206 | 207 | // Texture Glyph coordinate 208 | vertices[vertex_index + 4] = ch_data.bot_right.x - margin; 209 | vertices[vertex_index + 5] = ch_data.top_left.y; 210 | 211 | // Iterate 212 | vertex_index = vertex_index + 6; 213 | 214 | //__________________________________________________________________________________________ 215 | x += (ch_data.Advance >> 6) * scale; 216 | 217 | //__________________________________________________________________________________________ 218 | 219 | 220 | // Fix the index buffers 221 | // Set the node indices 222 | unsigned int t_id = ((indices_index / 6) * 4); 223 | // Triangle 0,1,2 224 | indices[indices_index + 0] = t_id + 0; 225 | indices[indices_index + 1] = t_id + 1; 226 | indices[indices_index + 2] = t_id + 2; 227 | 228 | // Triangle 2,3,0 229 | indices[indices_index + 3] = t_id + 2; 230 | indices[indices_index + 4] = t_id + 3; 231 | indices[indices_index + 5] = t_id + 0; 232 | 233 | // Increment 234 | indices_index = indices_index + 6; 235 | } 236 | 237 | } 238 | 239 | 240 | glm::vec2 label_text_store::rotate_pt(glm::vec2& rotate_about, glm::vec2 pt, float& rotation_angle) 241 | { 242 | // Return the rotation point 243 | glm::vec2 translated_pt = pt - rotate_about; 244 | 245 | // Apply rotation 246 | float radians = (rotation_angle * 3.14159365f) / 180.0f; // convert degrees to radians 247 | float cos_theta = cos(radians); 248 | float sin_theta = sin(radians); 249 | 250 | // Rotated point of the corners 251 | glm::vec2 rotated_pt = glm::vec2((translated_pt.x * cos_theta) - (translated_pt.y * sin_theta), 252 | (translated_pt.x * sin_theta) + (translated_pt.y * cos_theta)); 253 | 254 | return (rotated_pt + rotate_about); 255 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/label_text_store.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "buffers/gBuffers.h" 5 | #include "font_atlas.h" 6 | 7 | struct label_text 8 | { 9 | // Store the individual label 10 | const char* label; 11 | glm::vec2 label_loc; 12 | glm::vec3 label_color; 13 | float label_angle; 14 | float label_size; 15 | }; 16 | 17 | class label_text_store 18 | { 19 | // Stores all the labels 20 | public: 21 | font_atlas main_font; 22 | unsigned int total_char_count = 0; 23 | gBuffers label_buffers; 24 | std::vector labels; 25 | 26 | label_text_store(); 27 | ~label_text_store(); 28 | void init(); 29 | void add_text(const char* text, glm::vec2 text_loc, glm::vec3 text_color, 30 | float geom_scale, float font_angle, float font_size); 31 | void set_buffers(); 32 | void paint_text(); 33 | private: 34 | void get_buffer(label_text& label, float* vertices, unsigned int& vertex_index, unsigned int* indices, unsigned int& indices_index); 35 | glm::vec2 rotate_pt(glm::vec2& rotate_about, glm::vec2 pt, float& rotation_angle); 36 | 37 | }; 38 | -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/basic_frag_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec3 fColor; 4 | 5 | out vec4 FragColor; 6 | 7 | void main() 8 | { 9 | FragColor = vec4(fColor,1.0); 10 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/basic_vert_shader.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 aPos; 3 | layout (location = 1) in vec3 aColor; 4 | 5 | out vec3 fColor; 6 | 7 | void main() 8 | { 9 | gl_Position = vec4(aPos, 1.0); 10 | fColor = aColor; 11 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/shader.cpp: -------------------------------------------------------------------------------- 1 | #include "shader.h" 2 | 3 | shader::shader() 4 | :s_id(0), uniform_location_cache() 5 | { 6 | 7 | } 8 | 9 | // Constructor that takes vertex and fragment shader file names 10 | void shader::create_shader(const char* vertexFile, const char* fragmentFile) 11 | { 12 | // Load and compile the vertex shader 13 | unsigned int vertexShader = loadShader(GL_VERTEX_SHADER, vertexFile); 14 | 15 | // Load and compile the fragment shader 16 | unsigned int fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentFile); 17 | 18 | // Link the shader program 19 | linkProgram(vertexShader, fragmentShader); 20 | 21 | // Delete the individual shaders as they are no longer needed after linking 22 | glDeleteShader(vertexShader); 23 | glDeleteShader(fragmentShader); 24 | } 25 | 26 | // Destructor 27 | shader::~shader() 28 | { 29 | glDeleteProgram(this->s_id); 30 | } 31 | 32 | unsigned int shader::get_shader_id() const 33 | { 34 | return s_id; 35 | } 36 | 37 | // Load shader source from file and return as string 38 | std::string shader::loadShaderSource(const char* fileName) 39 | { 40 | std::string temp = ""; // Temporary string to store each line of the shader source 41 | std::string src = ""; // Final string to store the entire shader source 42 | 43 | std::ifstream in_file; // Input file stream for reading from file 44 | 45 | //std::filesystem::path original_dir = std::filesystem::current_path(); 46 | //std::filesystem::current_path("C:/Users/HFXMSZ/OneDrive - LR/ Documents/Programming/Other programs/Cpp_projects/Truss_static_analysis_cpp/Truss_static_analysis_cpp/src/geometry_store/shaders/"); 47 | 48 | // Open the file with the given file name 49 | in_file.open(fileName); 50 | 51 | // std::filesystem::current_path(original_dir); 52 | 53 | if (in_file.is_open()) // Check if file was successfully opened 54 | { 55 | while (std::getline(in_file, temp)) // Read each line from file 56 | src += temp + "\n"; // Append each line to the final shader source string with a newline character 57 | } 58 | else 59 | { 60 | std::cout << "ERROR::SHADER::COULD_NOT_OPEN_FILE: " << fileName << "\n"; // Print error message if file could not be opened 61 | } 62 | 63 | in_file.close(); // Close the file 64 | 65 | //// Replace the #version directive in the shader source with a default version number 66 | //src.replace(src.find("#version"), 12, "#version 330"); // Replace with desired version number 67 | 68 | return src; // Return the final shader source string 69 | } 70 | 71 | // Load shader source from file and compile shader 72 | unsigned int shader::loadShader(GLenum type,const char* fileName) 73 | { 74 | char infoLog[512]; 75 | int success; 76 | 77 | unsigned int shader = glCreateShader(type); // Create a shader object of given type 78 | std::string str_src = this->loadShaderSource(fileName); // Load shader source from file 79 | const char* src = str_src.c_str(); // Convert shader source to GLchar array 80 | glShaderSource(shader, 1, &src, NULL); // Set shader source 81 | glCompileShader(shader); // Compile shader source 82 | 83 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); // Check shader compilation status 84 | if (!success) 85 | { 86 | glGetShaderInfoLog(shader, 512, NULL, infoLog); // Get shader compilation error log 87 | std::cout << "ERROR::SHADER::COULD_NOT_COMPILE_SHADER: " << fileName << "\n"; 88 | std::cout << infoLog << "\n"; // Print shader compilation error log 89 | } 90 | 91 | return shader; // Return compiled shader object 92 | } 93 | 94 | 95 | // Link vertex and fragment shaders to create shader program 96 | void shader::linkProgram(unsigned int vertexShader, unsigned int fragmentShader) 97 | { 98 | char infoLog[512]; 99 | int success; 100 | 101 | this->s_id = glCreateProgram(); // Create a shader program object 102 | 103 | glAttachShader(this->s_id, vertexShader); // Attach vertex shader to shader program 104 | 105 | glAttachShader(this->s_id, fragmentShader); // Attach fragment shader to shader program 106 | 107 | glLinkProgram(this->s_id); // Link shader program 108 | 109 | glGetProgramiv(this->s_id, GL_LINK_STATUS, &success); // Check shader program linking status 110 | if (!success) 111 | { 112 | glGetProgramInfoLog(this->s_id, 512, NULL, infoLog); // Get shader program linking error log 113 | std::cout << "ERROR::SHADER::COULD_NOT_LINK_PROGRAM" << "\n"; 114 | std::cout << infoLog << "\n"; // Print shader program linking error log 115 | } 116 | 117 | glUseProgram(0); // Unbind shader program 118 | } 119 | 120 | int shader::get_uniform_location(const std::string uniform_name) 121 | { 122 | // Return the uniform location 123 | if (uniform_location_cache.find(uniform_name) != uniform_location_cache.end()) 124 | { 125 | return uniform_location_cache[uniform_name]; 126 | } 127 | 128 | // Uniform is not found in the hashtable ? Dictionary 129 | // So add it to the dictionary 130 | int uniform_location_id = glGetUniformLocation(this->s_id, uniform_name.c_str()); 131 | uniform_location_cache[uniform_name] = uniform_location_id; 132 | 133 | return uniform_location_id; 134 | } 135 | 136 | // Bind and un-Bind 137 | void shader::Bind() 138 | { 139 | glUseProgram(this->s_id); // Use the shader program 140 | } 141 | 142 | void shader::UnBind() 143 | { 144 | glUseProgram(0); // Un-use the shader program 145 | } 146 | 147 | //Set uniform functions 148 | void shader::setUniform(std::string name, float X, float Y) // Function to set a 2D float uniform 149 | { 150 | Bind(); // Use the shader program 151 | 152 | unsigned int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 153 | glUniform2f(uniformLocation, X, Y); // Set the 2D float uniform with the provided values for X and Y 154 | 155 | UnBind(); // Un-use the shader program 156 | } 157 | 158 | void shader::setUniform(std::string name, float X, float Y, float Z) // Function to set a 3D float uniform 159 | { 160 | Bind(); // Use the shader program 161 | 162 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 163 | glUniform3f(uniformLocation, X, Y, Z); // Set the 3D float uniform with the provided values for X, Y and Z 164 | 165 | UnBind(); // Un-use the shader program 166 | } 167 | 168 | void shader::setUniform(std::string name, float X, float Y, float Z, float W) // Function to set a 4D float uniform 169 | { 170 | Bind(); // Use the shader program 171 | 172 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 173 | glUniform4f(uniformLocation, X, Y, Z,W); // Set the 4D float uniform with the provided values for X, Y and Z 174 | 175 | UnBind(); // Un-use the shader program 176 | } 177 | 178 | void shader::setUniform(std::string name, float X) // Function to set a float uniform 179 | { 180 | Bind(); // Use the shader program 181 | 182 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 183 | glUniform1f(uniformLocation, X); // Set the 1D float uniform with the provided value for X 184 | 185 | UnBind(); // Un-use the shader program 186 | } 187 | 188 | void shader::setUniform(std::string name, int X) // Function to set an integer uniform 189 | { 190 | Bind(); // Use the shader program 191 | 192 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 193 | glUniform1i(uniformLocation, X); // Set the 1D int uniform with the provided value for X 194 | 195 | UnBind(); // Un-use the shader program 196 | } 197 | 198 | void shader::setUniform(std::string name, glm::mat3 X, bool transpose) // Function to set a mat3 uniform 199 | { 200 | Bind(); // Use the shader program 201 | 202 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 203 | 204 | if (transpose) 205 | { 206 | glUniformMatrix3fv(uniformLocation, 1, GL_TRUE, glm::value_ptr(glm::transpose(X))); // Set the mat3 uniform with the transpose of the provided matrix 207 | } 208 | else 209 | { 210 | glUniformMatrix3fv(uniformLocation, 1, GL_FALSE, glm::value_ptr(X)); // Set the mat3 uniform with the provided matrix 211 | } 212 | 213 | UnBind(); // Un-use the shader program 214 | } 215 | 216 | void shader::setUniform(std::string name, glm::mat4 X, bool transpose) // Function to set a mat4 uniform 217 | { 218 | Bind(); // Use the shader program 219 | 220 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 221 | 222 | if (transpose) 223 | { 224 | glUniformMatrix4fv(uniformLocation, 1, GL_TRUE, glm::value_ptr(glm::transpose(X))); // Set the mat4 uniform with the transpose of the provided matrix 225 | } 226 | else 227 | { 228 | glUniformMatrix4fv(uniformLocation, 1, GL_FALSE, glm::value_ptr(X)); // Set the mat4 uniform with the provided matrix 229 | } 230 | 231 | UnBind(); // Un-use the shader program 232 | } 233 | 234 | void shader::setUniform(std::string name, glm::vec4 X) // Function to set a vec4 uniform 235 | { 236 | Bind(); // Use the shader program 237 | 238 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 239 | 240 | glUniform4fv(uniformLocation, 1, glm::value_ptr(X)); // Set the vec4 uniform with the provided value for X 241 | 242 | UnBind(); // Un-use the shader program 243 | } 244 | 245 | void shader::setUniform(std::string name, glm::vec3 X) // Function to set a vec3 uniform 246 | { 247 | Bind(); // Use the shader program 248 | 249 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 250 | 251 | glUniform3fv(uniformLocation, 1, glm::value_ptr(X)); // Set the vec3 uniform with the provided value for X 252 | 253 | UnBind(); // Un-use the shader program 254 | } 255 | 256 | void shader::setUniform(std::string name, glm::vec2 X) // Function to set a vec2 uniform 257 | { 258 | Bind(); // Use the shader program 259 | 260 | int uniformLocation = glGetUniformLocation(this->s_id, name.c_str()); // Get the uniform location using the provided name 261 | 262 | glUniform2fv(uniformLocation, 1, glm::value_ptr(X)); // Set the vec2 uniform with the provided value for X 263 | 264 | UnBind(); // Un-use the shader program 265 | } 266 | 267 | void shader::setUniform(int i, unsigned int tid) // Function to set a texture uniform 268 | { 269 | Bind(); // Use the shader program 270 | 271 | // Activate the texture unit i 272 | glActiveTexture(GL_TEXTURE0 + i); 273 | 274 | // Bind the texture with the provided texture ID (tid) to the active texture unit 275 | glBindTexture(GL_TEXTURE_2D, tid); 276 | 277 | // Set the uniform value to the texture unit index i 278 | glUniform1i(glGetUniformLocation(this->s_id, "textureSampler"), i); 279 | 280 | UnBind(); // Un-use the shader program 281 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // https://github.com/Headturna/OpenGL-C---Tutorials/blob/master/Shader.h 20 | // https://github.com/MichaelMoroz/ShaderToy2CPP/blob/master/src/Shaders.cpp 21 | 22 | class shader 23 | { 24 | private: 25 | // Member variables 26 | unsigned int s_id; // OpenGL program ID 27 | std::unordered_map uniform_location_cache; 28 | std::string loadShaderSource(const char* fileName); // Function to load shader source from file 29 | unsigned int loadShader(GLenum type, const char* fileName); // Function to load a shader of given type 30 | void linkProgram(unsigned int vertexShader, unsigned int fragmentShader); // Function to link the shader program 31 | int get_uniform_location(const std::string uniform_name); 32 | public: 33 | // Constructors/Destructors 34 | shader(); 35 | ~shader(); // Destructor to clean up OpenGL resources 36 | 37 | void create_shader(const char* vertexFile, const char* fragmentFile);// Function that takes vertex and fragment shader file path 38 | // Shader usage functions 39 | void Bind(); // Function to use the shader program 40 | void UnBind(); // Function to unuse the shader program 41 | 42 | // Uniform setting functions 43 | void setUniform(std::string name, float X, float Y); // Function to set a 2D float uniform 44 | void setUniform(std::string name, float X, float Y, float Z); // Function to set a 3D float uniform 45 | void setUniform(std::string name, float X, float Y, float Z, float W); // Function to set a 4D float uniform 46 | void setUniform(std::string name, float X); // Function to set a float uniform 47 | void setUniform(std::string name, int X); // Function to set an integer uniform 48 | void setUniform(std::string name, glm::mat3 X, bool transpose); // Function to set a mat3 uniform 49 | void setUniform(std::string name, glm::mat4 X, bool transpose); // Function to set a mat4 uniform 50 | void setUniform(std::string name, glm::vec4 X); // Function to set a vec4 uniform 51 | void setUniform(std::string name, glm::vec3 X); // Function to set a vec3 uniform 52 | void setUniform(std::string name, glm::vec2 X); // Function to set a vec2 uniform 53 | void setUniform(int i, unsigned int tid); // Function to set a texture uniform 54 | unsigned int get_shader_id() const; 55 | }; 56 | -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/text_frag_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | uniform sampler2D u_Texture; 3 | 4 | in vec3 v_textureColor; 5 | in vec2 v_textureCoord; 6 | 7 | out vec4 f_Color; // fragment's final color (out to the fragment shader) 8 | 9 | void main() 10 | { 11 | vec4 texColor = vec4(1.0, 1.0, 1.0, texture(u_Texture, v_textureCoord).r); 12 | 13 | // vec4 texColor = texture(u_Texture, v_textureCoord); 14 | f_Color = vec4(v_textureColor,1.0f)*texColor; 15 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/text_vert_shader.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | uniform float zoomscale; 4 | 5 | layout(location = 0) in vec2 position; 6 | layout(location = 1) in vec2 origin; 7 | layout(location = 2) in vec2 textureCoord; 8 | 9 | out vec3 v_textureColor; 10 | out vec2 v_textureCoord; 11 | 12 | void main() 13 | { 14 | // apply zoom scaling and Rotation to model matrix 15 | mat4 scalingMatrix = mat4(1.0)*zoomscale; 16 | scalingMatrix[3][3] = 1.0f; 17 | 18 | // apply Translation to the final position 19 | vec4 finalPosition = scalingMatrix * vec4(position,0.0f,1.0f); 20 | 21 | // apply Translation to the text origin 22 | vec4 finalTextorigin = scalingMatrix * vec4(origin,0.0f,1.0f); 23 | 24 | // Remove the zoom scale 25 | vec2 scaled_pt = vec2(finalPosition.x - finalTextorigin.x,finalPosition.y - finalTextorigin.y) / zoomscale; 26 | 27 | // Set the final position of the vertex 28 | gl_Position = vec4(finalPosition.x + scaled_pt.x,finalPosition.y + scaled_pt.y, 0.0f, 1.0f); 29 | 30 | // Calculate texture coordinates for the glyph 31 | v_textureCoord = textureCoord; 32 | 33 | // Pass the texture color to the fragment shader 34 | v_textureColor = vec3(1.0f,1.0f,1.0f); 35 | } -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/ttf_CanadaDBNormal.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/src/shaders/ttf_CanadaDBNormal.ttf -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/ttf_CenturyGothic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/src/shaders/ttf_CenturyGothic.ttf -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/ttf_FreeSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/src/shaders/ttf_FreeSans.ttf -------------------------------------------------------------------------------- /opengl_textrendering/src/shaders/ttf_HyperFont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Samson-Mano/opengl_textrendering/65ac877b923abd24bb3de211e5a31a9dc7ffa2b1/opengl_textrendering/src/shaders/ttf_HyperFont.ttf --------------------------------------------------------------------------------