├── .gitignore ├── CMakeLists.txt ├── README.md ├── cmake └── FindSDL2.cmake ├── include ├── KHR │ └── khrplatform.h ├── glad │ └── glad.h └── stb_image.h ├── res ├── back.png ├── blendMap.png ├── bottom.png ├── dirt.png ├── dog.png ├── dragon.obj ├── fern.obj ├── fern.png ├── flower.png ├── front.png ├── grass.obj ├── grass.png ├── grassFlowers.png ├── grassModel.obj ├── grassTexture.png ├── grassy.png ├── health.png ├── heightmap.png ├── lamp.obj ├── lamp.png ├── left.png ├── lowPolyTree.obj ├── lowPolyTree.png ├── matchingNormalMap.png ├── mud.png ├── nightBack.png ├── nightBottom.png ├── nightFront.png ├── nightLeft.png ├── nightRight.png ├── nightTop.png ├── normal.png ├── normalMap.png ├── path.png ├── person.obj ├── pinkFlowers.png ├── playerTexture.png ├── right.png ├── stall.obj ├── stallTexture.png ├── stanfordBunny.obj ├── top.png ├── tree.obj ├── tree.png ├── waterDUDV.png └── white.png └── src ├── camera.cpp ├── camera.hpp ├── display_manager.cpp ├── display_manager.hpp ├── entity.cpp ├── entity.hpp ├── entity_renderer.cpp ├── entity_renderer.hpp ├── gl_handles.hpp ├── glad.c ├── gui_renderer.cpp ├── gui_renderer.hpp ├── gui_shader.cpp ├── gui_shader.hpp ├── gui_texture.cpp ├── gui_texture.hpp ├── light.cpp ├── light.hpp ├── loader.cpp ├── loader.hpp ├── main_game_loop.cpp ├── master_renderer.cpp ├── master_renderer.hpp ├── maths.cpp ├── maths.hpp ├── model_texture.cpp ├── model_texture.hpp ├── mouse_picker.cpp ├── mouse_picker.hpp ├── obj_loader.cpp ├── obj_loader.hpp ├── player.cpp ├── player.hpp ├── raw_model.cpp ├── raw_model.hpp ├── sdl_handles.hpp ├── shader_program.cpp ├── shader_program.hpp ├── shaders ├── fragment_shader.frag ├── gui_fragment_shader.frag ├── gui_vertex_shader.vert ├── skybox_fragment_shader.frag ├── skybox_vertex_shader.vert ├── terrain_fragment_shader.frag ├── terrain_vertex_shader.vert ├── vertex_shader.vert ├── water_fragment_shader.frag └── water_vertex_shader.vert ├── skybox_renderer.cpp ├── skybox_renderer.hpp ├── skybox_shader.cpp ├── skybox_shader.hpp ├── static_shader.cpp ├── static_shader.hpp ├── stb_image.c ├── stb_image.hpp ├── terrain.cpp ├── terrain.hpp ├── terrain_renderer.cpp ├── terrain_renderer.hpp ├── terrain_shader.cpp ├── terrain_shader.hpp ├── terrain_texture.cpp ├── terrain_texture.hpp ├── textured_model.cpp ├── textured_model.hpp ├── water_frame_buffers.cpp ├── water_frame_buffers.hpp ├── water_renderer.cpp ├── water_renderer.hpp ├── water_shader.cpp ├── water_shader.hpp ├── water_tile.cpp └── water_tile.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | build/ 3 | CMakeLists.txt.user 4 | .idea/ 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(jac C CXX) 4 | 5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${jac_SOURCE_DIR}/cmake") 6 | 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra") 8 | 9 | find_package(SDL2 REQUIRED) 10 | find_package(glm REQUIRED) 11 | 12 | add_executable(jac 13 | src/camera.cpp 14 | src/display_manager.cpp 15 | src/entity.cpp 16 | src/entity_renderer.cpp 17 | src/glad.c 18 | src/gui_renderer.cpp 19 | src/gui_shader.cpp 20 | src/gui_texture.cpp 21 | src/light.cpp 22 | src/loader.cpp 23 | src/main_game_loop.cpp 24 | src/master_renderer.cpp 25 | src/maths.cpp 26 | src/model_texture.cpp 27 | src/mouse_picker.cpp 28 | src/obj_loader.cpp 29 | src/player.cpp 30 | src/raw_model.cpp 31 | src/shader_program.cpp 32 | src/skybox_renderer.cpp 33 | src/skybox_shader.cpp 34 | src/static_shader.cpp 35 | src/stb_image.c 36 | src/terrain.cpp 37 | src/terrain_renderer.cpp 38 | src/terrain_shader.cpp 39 | src/terrain_texture.cpp 40 | src/textured_model.cpp 41 | # This is just so the files appear in QtCreator 42 | src/shaders/vertex_shader.vert 43 | src/shaders/fragment_shader.frag 44 | src/shaders/gui_vertex_shader.vert 45 | src/shaders/gui_fragment_shader.frag 46 | src/shaders/skybox_vertex_shader.vert 47 | src/shaders/skybox_fragment_shader.frag 48 | src/shaders/terrain_vertex_shader.vert 49 | src/shaders/terrain_fragment_shader.frag 50 | src/water_frame_buffers.cpp 51 | src/water_renderer.cpp 52 | src/water_shader.cpp 53 | src/water_tile.cpp) 54 | 55 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/shaders 56 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 57 | 58 | file(COPY ${jac_SOURCE_DIR}/res 59 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 60 | 61 | target_include_directories(jac PRIVATE 62 | "${jac_SOURCE_DIR}/include" 63 | ${GLM_INCLUDE_DIR} 64 | ${SDL2_INCLUDE_DIR} 65 | ) 66 | 67 | target_link_libraries(jac PRIVATE 68 | ${SDL2_LIBRARY} 69 | ) 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | A C++ implementation of the 3 | [ThinMatrix OpenGL tutorials on Youtube](https://www.youtube.com/playlist?list=PLRIWtICgwaX0u7Rf9zkZhLoLuZVfUksDP). 4 | The tutorials were originally written in Java, but and this is a fairly 5 | straightforward port -- so if you see things that aren't necessarily idiomatic 6 | C++, that's why. 7 | 8 | This code requires OpenGL 3.3, SDL2 and glm. 9 | 10 | As to why it's called jac... I don't know. Sorry. -------------------------------------------------------------------------------- /cmake/FindSDL2.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This module defines 3 | # SDL2_LIBRARY, the name of the library to link against 4 | # SDL2_FOUND, if false, do not try to link to SDL2 5 | # SDL2_INCLUDE_DIR, where to find SDL.h 6 | # 7 | # This module responds to the the flag: 8 | # SDL2_BUILDING_LIBRARY 9 | # If this is defined, then no SDL2main will be linked in because 10 | # only applications need main(). 11 | # Otherwise, it is assumed you are building an application and this 12 | # module will attempt to locate and set the the proper link flags 13 | # as part of the returned SDL2_LIBRARY variable. 14 | # 15 | # Don't forget to include SDLmain.h and SDLmain.m your project for the 16 | # OS X framework based version. (Other versions link to -lSDL2main which 17 | # this module will try to find on your behalf.) Also for OS X, this 18 | # module will automatically add the -framework Cocoa on your behalf. 19 | # 20 | # 21 | # Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration 22 | # and no SDL2_LIBRARY, it means CMake did not find your SDL2 library 23 | # (SDL2.dll, libsdl2.so, SDL2.framework, etc). 24 | # Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. 25 | # Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value 26 | # as appropriate. These values are used to generate the final SDL2_LIBRARY 27 | # variable, but when these values are unset, SDL2_LIBRARY does not get created. 28 | # 29 | # 30 | # $SDL2DIR is an environment variable that would 31 | # correspond to the ./configure --prefix=$SDL2DIR 32 | # used in building SDL2. 33 | # l.e.galup 9-20-02 34 | # 35 | # Modified by Eric Wing. 36 | # Added code to assist with automated building by using environmental variables 37 | # and providing a more controlled/consistent search behavior. 38 | # Added new modifications to recognize OS X frameworks and 39 | # additional Unix paths (FreeBSD, etc). 40 | # Also corrected the header search path to follow "proper" SDL guidelines. 41 | # Added a search for SDL2main which is needed by some platforms. 42 | # Added a search for threads which is needed by some platforms. 43 | # Added needed compile switches for MinGW. 44 | # 45 | # On OSX, this will prefer the Framework version (if found) over others. 46 | # People will have to manually change the cache values of 47 | # SDL2_LIBRARY to override this selection or set the CMake environment 48 | # CMAKE_INCLUDE_PATH to modify the search paths. 49 | # 50 | # Note that the header path has changed from SDL2/SDL.h to just SDL.h 51 | # This needed to change because "proper" SDL convention 52 | # is #include "SDL.h", not . This is done for portability 53 | # reasons because not all systems place things in SDL2/ (see FreeBSD). 54 | 55 | #============================================================================= 56 | # Copyright 2003-2009 Kitware, Inc. 57 | # 58 | # Distributed under the OSI-approved BSD License (the "License"); 59 | # see accompanying file Copyright.txt for details. 60 | # 61 | # This software is distributed WITHOUT ANY WARRANTY; without even the 62 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 63 | # See the License for more information. 64 | #============================================================================= 65 | # (To distribute this file outside of CMake, substitute the full 66 | # License text for the above reference.) 67 | 68 | SET(SDL2_SEARCH_PATHS 69 | ~/Library/Frameworks 70 | /Library/Frameworks 71 | /usr/local 72 | /usr 73 | /sw # Fink 74 | /opt/local # DarwinPorts 75 | /opt/csw # Blastwave 76 | /opt 77 | ) 78 | 79 | FIND_PATH(SDL2_INCLUDE_DIR SDL.h 80 | HINTS 81 | $ENV{SDL2DIR} 82 | PATH_SUFFIXES include/SDL2 include 83 | PATHS ${SDL2_SEARCH_PATHS} 84 | ) 85 | 86 | FIND_LIBRARY(SDL2_LIBRARY_TEMP 87 | NAMES SDL2 88 | HINTS 89 | $ENV{SDL2DIR} 90 | PATH_SUFFIXES lib64 lib 91 | PATHS ${SDL2_SEARCH_PATHS} 92 | ) 93 | 94 | IF(NOT SDL2_BUILDING_LIBRARY) 95 | IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") 96 | # Non-OS X framework versions expect you to also dynamically link to 97 | # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms 98 | # seem to provide SDL2main for compatibility even though they don't 99 | # necessarily need it. 100 | FIND_LIBRARY(SDL2MAIN_LIBRARY 101 | NAMES SDL2main 102 | HINTS 103 | $ENV{SDL2DIR} 104 | PATH_SUFFIXES lib64 lib 105 | PATHS ${SDL2_SEARCH_PATHS} 106 | ) 107 | ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") 108 | ENDIF(NOT SDL2_BUILDING_LIBRARY) 109 | 110 | # SDL2 may require threads on your system. 111 | # The Apple build may not need an explicit flag because one of the 112 | # frameworks may already provide it. 113 | # But for non-OSX systems, I will use the CMake Threads package. 114 | IF(NOT APPLE) 115 | FIND_PACKAGE(Threads) 116 | ENDIF(NOT APPLE) 117 | 118 | # MinGW needs an additional library, mwindows 119 | # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows 120 | # (Actually on second look, I think it only needs one of the m* libraries.) 121 | IF(MINGW) 122 | SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") 123 | ENDIF(MINGW) 124 | 125 | IF(SDL2_LIBRARY_TEMP) 126 | # For SDL2main 127 | IF(NOT SDL2_BUILDING_LIBRARY) 128 | IF(SDL2MAIN_LIBRARY) 129 | SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) 130 | ENDIF(SDL2MAIN_LIBRARY) 131 | ENDIF(NOT SDL2_BUILDING_LIBRARY) 132 | 133 | # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. 134 | # CMake doesn't display the -framework Cocoa string in the UI even 135 | # though it actually is there if I modify a pre-used variable. 136 | # I think it has something to do with the CACHE STRING. 137 | # So I use a temporary variable until the end so I can set the 138 | # "real" variable in one-shot. 139 | IF(APPLE) 140 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") 141 | ENDIF(APPLE) 142 | 143 | # For threads, as mentioned Apple doesn't need this. 144 | # In fact, there seems to be a problem if I used the Threads package 145 | # and try using this line, so I'm just skipping it entirely for OS X. 146 | IF(NOT APPLE) 147 | SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) 148 | ENDIF(NOT APPLE) 149 | 150 | # For MinGW library 151 | IF(MINGW) 152 | SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) 153 | ENDIF(MINGW) 154 | 155 | # Set the final string here so the GUI reflects the final state. 156 | SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") 157 | # Set the temp variable to INTERNAL so it is not seen in the CMake GUI 158 | SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") 159 | ENDIF(SDL2_LIBRARY_TEMP) 160 | 161 | INCLUDE(FindPackageHandleStandardArgs) 162 | 163 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) 164 | 165 | -------------------------------------------------------------------------------- /include/KHR/khrplatform.h: -------------------------------------------------------------------------------- 1 | #ifndef __khrplatform_h_ 2 | #define __khrplatform_h_ 3 | 4 | /* 5 | ** Copyright (c) 2008-2009 The Khronos Group Inc. 6 | ** 7 | ** Permission is hereby granted, free of charge, to any person obtaining a 8 | ** copy of this software and/or associated documentation files (the 9 | ** "Materials"), to deal in the Materials without restriction, including 10 | ** without limitation the rights to use, copy, modify, merge, publish, 11 | ** distribute, sublicense, and/or sell copies of the Materials, and to 12 | ** permit persons to whom the Materials are furnished to do so, subject to 13 | ** the following conditions: 14 | ** 15 | ** The above copyright notice and this permission notice shall be included 16 | ** in all copies or substantial portions of the Materials. 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 | */ 26 | 27 | /* Khronos platform-specific types and definitions. 28 | * 29 | * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $ 30 | * 31 | * Adopters may modify this file to suit their platform. Adopters are 32 | * encouraged to submit platform specific modifications to the Khronos 33 | * group so that they can be included in future versions of this file. 34 | * Please submit changes by sending them to the public Khronos Bugzilla 35 | * (http://khronos.org/bugzilla) by filing a bug against product 36 | * "Khronos (general)" component "Registry". 37 | * 38 | * A predefined template which fills in some of the bug fields can be 39 | * reached using http://tinyurl.com/khrplatform-h-bugreport, but you 40 | * must create a Bugzilla login first. 41 | * 42 | * 43 | * See the Implementer's Guidelines for information about where this file 44 | * should be located on your system and for more details of its use: 45 | * http://www.khronos.org/registry/implementers_guide.pdf 46 | * 47 | * This file should be included as 48 | * #include 49 | * by Khronos client API header files that use its types and defines. 50 | * 51 | * The types in khrplatform.h should only be used to define API-specific types. 52 | * 53 | * Types defined in khrplatform.h: 54 | * khronos_int8_t signed 8 bit 55 | * khronos_uint8_t unsigned 8 bit 56 | * khronos_int16_t signed 16 bit 57 | * khronos_uint16_t unsigned 16 bit 58 | * khronos_int32_t signed 32 bit 59 | * khronos_uint32_t unsigned 32 bit 60 | * khronos_int64_t signed 64 bit 61 | * khronos_uint64_t unsigned 64 bit 62 | * khronos_intptr_t signed same number of bits as a pointer 63 | * khronos_uintptr_t unsigned same number of bits as a pointer 64 | * khronos_ssize_t signed size 65 | * khronos_usize_t unsigned size 66 | * khronos_float_t signed 32 bit floating point 67 | * khronos_time_ns_t unsigned 64 bit time in nanoseconds 68 | * khronos_utime_nanoseconds_t unsigned time interval or absolute time in 69 | * nanoseconds 70 | * khronos_stime_nanoseconds_t signed time interval in nanoseconds 71 | * khronos_boolean_enum_t enumerated boolean type. This should 72 | * only be used as a base type when a client API's boolean type is 73 | * an enum. Client APIs which use an integer or other type for 74 | * booleans cannot use this as the base type for their boolean. 75 | * 76 | * Tokens defined in khrplatform.h: 77 | * 78 | * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. 79 | * 80 | * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. 81 | * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. 82 | * 83 | * Calling convention macros defined in this file: 84 | * KHRONOS_APICALL 85 | * KHRONOS_APIENTRY 86 | * KHRONOS_APIATTRIBUTES 87 | * 88 | * These may be used in function prototypes as: 89 | * 90 | * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( 91 | * int arg1, 92 | * int arg2) KHRONOS_APIATTRIBUTES; 93 | */ 94 | 95 | /*------------------------------------------------------------------------- 96 | * Definition of KHRONOS_APICALL 97 | *------------------------------------------------------------------------- 98 | * This precedes the return type of the function in the function prototype. 99 | */ 100 | #if defined(_WIN32) && !defined(__SCITECH_SNAP__) 101 | # define KHRONOS_APICALL __declspec(dllimport) 102 | #elif defined (__SYMBIAN32__) 103 | # define KHRONOS_APICALL IMPORT_C 104 | #else 105 | # define KHRONOS_APICALL 106 | #endif 107 | 108 | /*------------------------------------------------------------------------- 109 | * Definition of KHRONOS_APIENTRY 110 | *------------------------------------------------------------------------- 111 | * This follows the return type of the function and precedes the function 112 | * name in the function prototype. 113 | */ 114 | #if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) 115 | /* Win32 but not WinCE */ 116 | # define KHRONOS_APIENTRY __stdcall 117 | #else 118 | # define KHRONOS_APIENTRY 119 | #endif 120 | 121 | /*------------------------------------------------------------------------- 122 | * Definition of KHRONOS_APIATTRIBUTES 123 | *------------------------------------------------------------------------- 124 | * This follows the closing parenthesis of the function prototype arguments. 125 | */ 126 | #if defined (__ARMCC_2__) 127 | #define KHRONOS_APIATTRIBUTES __softfp 128 | #else 129 | #define KHRONOS_APIATTRIBUTES 130 | #endif 131 | 132 | /*------------------------------------------------------------------------- 133 | * basic type definitions 134 | *-----------------------------------------------------------------------*/ 135 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) 136 | 137 | 138 | /* 139 | * Using 140 | */ 141 | #include 142 | typedef int32_t khronos_int32_t; 143 | typedef uint32_t khronos_uint32_t; 144 | typedef int64_t khronos_int64_t; 145 | typedef uint64_t khronos_uint64_t; 146 | #define KHRONOS_SUPPORT_INT64 1 147 | #define KHRONOS_SUPPORT_FLOAT 1 148 | 149 | #elif defined(__VMS ) || defined(__sgi) 150 | 151 | /* 152 | * Using 153 | */ 154 | #include 155 | typedef int32_t khronos_int32_t; 156 | typedef uint32_t khronos_uint32_t; 157 | typedef int64_t khronos_int64_t; 158 | typedef uint64_t khronos_uint64_t; 159 | #define KHRONOS_SUPPORT_INT64 1 160 | #define KHRONOS_SUPPORT_FLOAT 1 161 | 162 | #elif defined(_WIN32) && !defined(__SCITECH_SNAP__) 163 | 164 | /* 165 | * Win32 166 | */ 167 | typedef __int32 khronos_int32_t; 168 | typedef unsigned __int32 khronos_uint32_t; 169 | typedef __int64 khronos_int64_t; 170 | typedef unsigned __int64 khronos_uint64_t; 171 | #define KHRONOS_SUPPORT_INT64 1 172 | #define KHRONOS_SUPPORT_FLOAT 1 173 | 174 | #elif defined(__sun__) || defined(__digital__) 175 | 176 | /* 177 | * Sun or Digital 178 | */ 179 | typedef int khronos_int32_t; 180 | typedef unsigned int khronos_uint32_t; 181 | #if defined(__arch64__) || defined(_LP64) 182 | typedef long int khronos_int64_t; 183 | typedef unsigned long int khronos_uint64_t; 184 | #else 185 | typedef long long int khronos_int64_t; 186 | typedef unsigned long long int khronos_uint64_t; 187 | #endif /* __arch64__ */ 188 | #define KHRONOS_SUPPORT_INT64 1 189 | #define KHRONOS_SUPPORT_FLOAT 1 190 | 191 | #elif 0 192 | 193 | /* 194 | * Hypothetical platform with no float or int64 support 195 | */ 196 | typedef int khronos_int32_t; 197 | typedef unsigned int khronos_uint32_t; 198 | #define KHRONOS_SUPPORT_INT64 0 199 | #define KHRONOS_SUPPORT_FLOAT 0 200 | 201 | #else 202 | 203 | /* 204 | * Generic fallback 205 | */ 206 | #include 207 | typedef int32_t khronos_int32_t; 208 | typedef uint32_t khronos_uint32_t; 209 | typedef int64_t khronos_int64_t; 210 | typedef uint64_t khronos_uint64_t; 211 | #define KHRONOS_SUPPORT_INT64 1 212 | #define KHRONOS_SUPPORT_FLOAT 1 213 | 214 | #endif 215 | 216 | 217 | /* 218 | * Types that are (so far) the same on all platforms 219 | */ 220 | typedef signed char khronos_int8_t; 221 | typedef unsigned char khronos_uint8_t; 222 | typedef signed short int khronos_int16_t; 223 | typedef unsigned short int khronos_uint16_t; 224 | 225 | /* 226 | * Types that differ between LLP64 and LP64 architectures - in LLP64, 227 | * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears 228 | * to be the only LLP64 architecture in current use. 229 | */ 230 | #ifdef _WIN64 231 | typedef signed long long int khronos_intptr_t; 232 | typedef unsigned long long int khronos_uintptr_t; 233 | typedef signed long long int khronos_ssize_t; 234 | typedef unsigned long long int khronos_usize_t; 235 | #else 236 | typedef signed long int khronos_intptr_t; 237 | typedef unsigned long int khronos_uintptr_t; 238 | typedef signed long int khronos_ssize_t; 239 | typedef unsigned long int khronos_usize_t; 240 | #endif 241 | 242 | #if KHRONOS_SUPPORT_FLOAT 243 | /* 244 | * Float type 245 | */ 246 | typedef float khronos_float_t; 247 | #endif 248 | 249 | #if KHRONOS_SUPPORT_INT64 250 | /* Time types 251 | * 252 | * These types can be used to represent a time interval in nanoseconds or 253 | * an absolute Unadjusted System Time. Unadjusted System Time is the number 254 | * of nanoseconds since some arbitrary system event (e.g. since the last 255 | * time the system booted). The Unadjusted System Time is an unsigned 256 | * 64 bit value that wraps back to 0 every 584 years. Time intervals 257 | * may be either signed or unsigned. 258 | */ 259 | typedef khronos_uint64_t khronos_utime_nanoseconds_t; 260 | typedef khronos_int64_t khronos_stime_nanoseconds_t; 261 | #endif 262 | 263 | /* 264 | * Dummy value used to pad enum types to 32 bits. 265 | */ 266 | #ifndef KHRONOS_MAX_ENUM 267 | #define KHRONOS_MAX_ENUM 0x7FFFFFFF 268 | #endif 269 | 270 | /* 271 | * Enumerated boolean type 272 | * 273 | * Values other than zero should be considered to be true. Therefore 274 | * comparisons should not be made against KHRONOS_TRUE. 275 | */ 276 | typedef enum { 277 | KHRONOS_FALSE = 0, 278 | KHRONOS_TRUE = 1, 279 | KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM 280 | } khronos_boolean_enum_t; 281 | 282 | #endif /* __khrplatform_h_ */ 283 | -------------------------------------------------------------------------------- /res/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/back.png -------------------------------------------------------------------------------- /res/blendMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/blendMap.png -------------------------------------------------------------------------------- /res/bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/bottom.png -------------------------------------------------------------------------------- /res/dirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/dirt.png -------------------------------------------------------------------------------- /res/dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/dog.png -------------------------------------------------------------------------------- /res/fern.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.67 (sub 0) OBJ File: 'fern.blend' 2 | # www.blender.org 3 | o Plane 4 | v -1.668906 1.421207 -4.981303 5 | v 1.291248 1.274556 -4.874573 6 | v -1.681098 2.133895 -4.624559 7 | v 1.441855 2.133895 -4.624559 8 | v -1.716799 2.696792 -3.607163 9 | v 1.406155 2.587040 -3.607163 10 | v -1.561477 2.636679 -1.975693 11 | v 1.561477 2.470482 -1.975693 12 | v -1.347036 1.668626 -1.121537 13 | v 1.561477 1.857010 -0.942828 14 | v -1.561477 -0.004097 -0.036216 15 | v 1.561477 -0.004097 -0.036216 16 | v 4.922924 2.330723 -2.113493 17 | v 4.930951 2.184072 0.848574 18 | v 4.372616 2.743763 -2.092158 19 | v 4.493601 2.743764 1.028451 20 | v 3.455437 2.912039 -2.056599 21 | v 3.576422 2.802288 1.064010 22 | v 1.942091 2.636679 -1.997928 23 | v 2.063076 2.470482 1.122681 24 | v 1.096885 1.668625 -1.750557 25 | v 1.030987 1.857010 1.162695 26 | v 0.004071 -0.004097 -1.922791 27 | v 0.125055 -0.004097 1.197818 28 | v 5.066892 1.391006 0.895784 29 | v 3.068532 1.226996 3.537834 30 | v 4.896961 2.123907 0.870659 31 | v 2.891804 2.123907 3.730312 32 | v 4.156424 2.763720 0.489422 33 | v 2.151268 2.640977 3.349074 34 | v 2.614438 2.708673 -0.523145 35 | v 0.609281 2.522805 2.336507 36 | v 1.694611 1.626036 -0.875212 37 | v -0.336501 1.836719 1.673335 38 | v 0.838482 -0.244677 -1.768426 39 | v -1.166676 -0.244677 1.091226 40 | v 1.019397 2.313956 4.808662 41 | v -1.755515 2.175439 4.451704 42 | v 1.067131 2.704086 4.290682 43 | v -1.870153 2.704086 4.020000 44 | v 1.146687 2.863028 3.427385 45 | v -1.790596 2.759363 3.156702 46 | v 1.277956 2.602941 2.002943 47 | v -1.659327 2.445963 1.732260 48 | v 1.150299 1.688583 1.180983 49 | v -1.569803 1.866519 0.760803 50 | v 1.446060 0.108644 0.178775 51 | v -1.491222 0.108645 -0.091908 52 | v -2.841108 2.359943 5.062696 53 | v -4.854967 2.199116 2.513874 54 | v -2.381020 2.812909 4.671439 55 | v -4.599705 2.812910 2.062436 56 | v -1.614207 2.997452 4.019345 57 | v -3.832892 2.877091 1.410342 58 | v -0.348966 2.695474 2.943390 59 | v -2.567650 2.513212 0.334387 60 | v 0.212271 1.633845 2.157409 61 | v -1.704767 1.840439 -0.399406 62 | v 1.271327 -0.200569 1.565499 63 | v -0.947357 -0.200569 -1.043504 64 | v -6.274055 1.495219 2.121059 65 | v -6.142600 1.319109 -1.433610 66 | v -5.544260 2.263995 1.986592 67 | v -5.540795 2.263996 -1.763698 68 | v -4.359546 2.953154 1.726256 69 | v -4.356080 2.821356 -2.024032 70 | v -2.407223 2.758862 1.710761 71 | v -2.403757 2.559280 -2.039528 72 | v -1.381247 1.596347 1.454191 73 | v -1.163412 1.822574 -2.038382 74 | v -0.078146 -0.412391 1.712912 75 | v -0.074680 -0.412391 -2.037376 76 | v -5.393490 2.359763 -2.091071 77 | v -3.270963 2.199023 -4.547807 78 | v -4.922800 2.812483 -1.713156 79 | v -2.779778 2.812484 -4.382275 80 | v -4.138320 2.996925 -1.083301 81 | v -1.995298 2.876630 -3.752418 82 | v -2.843926 2.695112 -0.044037 83 | v -0.700904 2.512949 -2.713154 84 | v -1.966746 1.634059 0.358820 85 | v 0.181862 1.840542 -2.004385 86 | v -1.186299 -0.199359 1.286863 87 | v 0.956723 -0.199359 -1.382254 88 | v -3.411818 3.548868 0.997281 89 | v -2.987591 3.599077 -1.523562 90 | v -2.848599 3.707952 1.095761 91 | v -2.444523 3.919941 -1.557639 92 | v -2.065775 3.556531 1.202876 93 | v -1.694590 3.680621 -1.462553 94 | v -0.939843 2.863784 1.318995 95 | v -0.585573 2.942669 -1.352623 96 | v -0.520648 1.836716 1.113190 97 | v 0.054735 2.129301 -1.320096 98 | v -0.183668 0.144097 1.216864 99 | v 0.220408 0.356086 -1.436535 100 | v -2.752246 3.548868 -2.331894 101 | v -0.428357 3.599077 -3.396862 102 | v -2.517365 3.707952 -1.810603 103 | v -0.095124 3.919941 -2.966700 104 | v -2.166277 3.556531 -1.102773 105 | v 0.247442 3.680621 -2.292838 106 | v -1.629914 2.863784 -0.106017 107 | v 0.779423 2.942669 -1.313553 108 | v -1.224182 1.836715 0.125201 109 | v 1.112171 2.129301 -0.765528 110 | v -1.120676 0.144097 0.462233 111 | v 1.301564 0.356086 -0.693862 112 | v 1.179569 3.548868 -3.299581 113 | v 3.068619 3.599077 -1.577340 114 | v 0.791671 3.707952 -2.879523 115 | v 2.803056 3.919941 -1.102408 116 | v 0.345733 3.637383 -2.162762 117 | v 2.385048 3.761473 -0.406775 118 | v -0.430031 2.863784 -1.396071 119 | v 1.623650 2.942669 0.349049 120 | v -0.484141 1.836715 -0.932226 121 | v 1.249424 2.129301 0.869633 122 | v -0.753842 0.144098 -0.705146 123 | v 1.257542 0.356086 1.071969 124 | v 3.478751 3.063767 0.129736 125 | v 2.508179 3.113976 2.494606 126 | v 2.969543 3.472751 -0.191974 127 | v 1.989343 3.684741 2.306629 128 | v 2.194941 3.556531 -0.538472 129 | v 1.244161 3.680621 1.979129 130 | v 1.122468 2.863784 -0.900428 131 | v 0.186821 2.942669 1.626945 132 | v 0.668168 1.836715 -0.792301 133 | v -0.430486 2.129301 1.453785 134 | v 0.362412 0.144098 -0.967850 135 | v -0.617787 0.356086 1.530752 136 | v 1.723514 3.227772 2.919589 137 | v -0.813319 3.277982 3.234388 138 | v 1.606172 3.518214 2.393483 139 | v -1.051909 3.730203 2.765519 140 | v 1.425735 3.556531 1.529277 141 | v -1.234463 3.680621 1.936269 142 | v 1.214835 2.863784 0.417193 143 | v -1.446452 2.942669 0.842165 144 | v 0.897690 1.836715 0.074411 145 | v -1.598496 2.129301 0.219321 146 | v 0.900611 0.144098 -0.278144 147 | v -1.757470 0.356086 0.093891 148 | vt 0.261788 0.894097 149 | vt 0.741905 0.894097 150 | vt 0.261788 0.999931 151 | vt 0.261788 0.750634 152 | vt 0.741905 0.750634 153 | vt 0.261788 0.513983 154 | vt 0.741905 0.513983 155 | vt 0.261788 0.307545 156 | vt 0.741905 0.307545 157 | vt 0.261788 0.000069 158 | vt 0.741905 0.000069 159 | vt 0.741905 0.999931 160 | vn 0.012848 0.702567 -0.711478 161 | vn 0.020722 0.682089 -0.730949 162 | vn 0.008454 0.417798 -0.908475 163 | vn 0.034089 0.970763 -0.237495 164 | vn 0.028413 0.982147 -0.185919 165 | vn -0.002197 0.931425 0.363872 166 | vn 0.050600 0.950804 0.305551 167 | vn -0.060060 0.579974 0.812403 168 | vn -0.036378 0.647877 0.760857 169 | vn 0.000000 0.544298 0.838862 170 | vn -0.051668 0.478774 0.876400 171 | vn 0.409406 0.911954 0.025819 172 | vn 0.432630 0.901395 -0.016755 173 | vn 0.762535 0.646565 -0.021699 174 | vn -0.002838 0.999115 0.041627 175 | vn -0.064425 0.997650 0.023103 176 | vn -0.440352 0.897580 0.020173 177 | vn -0.361736 0.930509 0.057314 178 | vn -0.797571 0.600513 -0.056856 179 | vn -0.745903 0.665731 0.019196 180 | vn -0.861782 0.506851 -0.018891 181 | vn -0.898312 0.437910 0.034822 182 | vn 0.698874 0.494675 0.516556 183 | vn 0.674551 0.550340 0.491989 184 | vn 0.814081 0.058443 0.577746 185 | vn 0.238380 0.950316 0.200171 186 | vn 0.172155 0.971587 0.162389 187 | vn -0.299814 0.931639 -0.205206 188 | vn -0.266366 0.954711 -0.132359 189 | vn -0.600360 0.600513 -0.528123 190 | vn -0.605304 0.665731 -0.436293 191 | vn -0.674459 0.506851 -0.536790 192 | vn -0.736076 0.437910 -0.516129 193 | vn -0.036775 0.916135 0.399121 194 | vn -0.080782 0.901364 0.425428 195 | vn -0.066225 0.776391 0.626728 196 | vn -0.025605 0.999512 -0.017548 197 | vn -0.027863 0.996460 -0.078982 198 | vn -0.003967 0.883175 -0.468978 199 | vn 0.045595 0.915891 -0.398785 200 | vn 0.083438 0.617115 -0.782434 201 | vn 0.155522 0.675375 -0.720847 202 | vn 0.076968 0.544298 -0.835322 203 | vn 0.131870 0.478774 -0.867946 204 | vn -0.305338 0.916135 0.259651 205 | vn -0.355174 0.901364 0.247688 206 | vn -0.485519 0.776391 0.401807 207 | vn -0.005890 0.999725 -0.022248 208 | vn 0.027192 0.996612 -0.077395 209 | vn 0.333567 0.880856 -0.335856 210 | vn 0.311014 0.913816 -0.261086 211 | vn 0.606677 0.617115 -0.501083 212 | vn 0.615162 0.675375 -0.406659 213 | vn 0.639058 0.544298 -0.543443 214 | vn 0.701102 0.478774 -0.528367 215 | vn -0.626392 0.779382 -0.011170 216 | vn -0.616840 0.786798 -0.020203 217 | vn -0.752464 0.658498 -0.011689 218 | vn -0.232734 0.971923 -0.034364 219 | vn -0.149419 0.988311 -0.029939 220 | vn 0.432173 0.900845 -0.040376 221 | vn 0.368816 0.929472 0.002625 222 | vn 0.786767 0.617115 0.011994 223 | vn 0.731986 0.675375 0.089389 224 | vn 0.838862 0.544298 0.000763 225 | vn 0.876339 0.478774 0.052461 226 | vn -0.312540 0.916135 -0.250923 227 | vn -0.310190 0.901364 -0.302133 228 | vn -0.486099 0.776391 -0.401105 229 | vn 0.020722 0.999725 -0.009980 230 | vn 0.081118 0.996612 0.012116 231 | vn 0.392682 0.880856 0.264290 232 | vn 0.315012 0.913816 0.256233 233 | vn 0.606433 0.617115 0.501389 234 | vn 0.515305 0.675375 0.527512 235 | vn 0.654134 0.544298 0.525193 236 | vn 0.651021 0.478774 0.588977 237 | vn -0.039766 0.997467 0.058840 238 | vn -0.070223 0.996551 0.043672 239 | vn -0.312082 0.949828 0.019776 240 | vn 0.351970 0.931425 0.092380 241 | vn 0.406476 0.907346 0.107028 242 | vn 0.748741 0.650807 0.125645 243 | vn 0.693106 0.701834 0.164220 244 | vn 0.941008 0.287820 0.177740 245 | vn 0.899045 0.355663 0.255348 246 | vn 0.965636 0.202216 0.163182 247 | vn 0.969817 0.123722 0.209998 248 | vn -0.071017 0.997467 0.000122 249 | vn -0.075594 0.996551 -0.033570 250 | vn -0.191656 0.949828 -0.247078 251 | vn 0.121281 0.931425 0.343089 252 | vn 0.139744 0.907346 0.396405 253 | vn 0.316568 0.650807 0.690054 254 | vn 0.253426 0.701834 0.665700 255 | vn 0.381481 0.287820 0.878384 256 | vn 0.293710 0.355663 0.887234 257 | vn 0.407361 0.202216 0.890561 258 | vn 0.370983 0.123722 0.920347 259 | vn 0.044221 0.993347 -0.106052 260 | vn 0.014801 0.990722 -0.134922 261 | vn 0.269295 0.877132 -0.397565 262 | vn -0.255837 0.938749 0.230781 263 | vn -0.302591 0.912412 0.275491 264 | vn -0.551134 0.636799 0.539171 265 | vn -0.469649 0.713095 0.520463 266 | vn -0.716178 0.263527 0.646229 267 | vn -0.648152 0.347850 0.677389 268 | vn -0.701132 0.155553 0.695822 269 | vn -0.664724 0.081668 0.742607 270 | vn 0.327616 0.942656 0.063509 271 | vn 0.362804 0.927641 0.088351 272 | vn 0.580432 0.796350 0.169958 273 | vn -0.204443 0.971740 -0.117893 274 | vn -0.237220 0.959471 -0.151952 275 | vn -0.667226 0.674642 -0.315622 276 | vn -0.624378 0.736290 -0.260781 277 | vn -0.852535 0.263527 -0.451338 278 | vn -0.858486 0.347850 -0.376751 279 | vn -0.893948 0.155553 -0.420240 280 | vn -0.925413 0.081668 -0.369976 281 | vn 0.088076 0.954680 0.284280 282 | vn 0.097964 0.957030 0.272896 283 | vn 0.140873 0.767968 0.624775 284 | vn 0.011750 0.963805 -0.266305 285 | vn -0.005890 0.945097 -0.326640 286 | vn -0.052400 0.674642 -0.736229 287 | vn -0.079134 0.736290 -0.672018 288 | vn -0.025086 0.263527 -0.964324 289 | vn -0.092990 0.347850 -0.932920 290 | vn -0.072512 0.155553 -0.985137 291 | vn -0.131748 0.081668 -0.987884 292 | vn 0.048097 0.271249 -0.961303 293 | vn 0.600787 0.798486 0.037904 294 | vn 0.775353 0.200293 0.598895 295 | vn -0.130985 0.609851 0.781579 296 | vn -0.640095 0.609851 0.467238 297 | vn -0.851009 0.521989 -0.057314 298 | vn -0.579485 0.609851 -0.540574 299 | vn -0.510666 0.856990 -0.068850 300 | vn -0.229835 0.856990 -0.461165 301 | vn 0.166631 0.963195 -0.210852 302 | vn 0.670217 0.694968 0.260292 303 | vn 0.075594 0.879971 0.468917 304 | s 1 305 | f 3/1/1 4/2/2 1/3/3 306 | f 5/4/4 6/5/5 3/1/1 307 | f 7/6/6 8/7/7 6/5/5 308 | f 9/8/8 10/9/9 7/6/6 309 | f 11/10/10 12/11/11 9/8/8 310 | f 15/1/12 16/2/13 14/12/14 311 | f 17/4/15 18/5/16 15/1/12 312 | f 19/6/17 20/7/18 17/4/15 313 | f 21/8/19 22/9/20 19/6/17 314 | f 23/10/21 24/11/22 22/9/20 315 | f 27/1/23 28/2/24 26/12/25 316 | f 29/4/26 30/5/27 28/2/24 317 | f 31/6/28 32/7/29 29/4/26 318 | f 33/8/30 34/9/31 31/6/28 319 | f 35/10/32 36/11/33 34/9/31 320 | f 39/1/34 40/2/35 37/3/36 321 | f 41/4/37 42/5/38 40/2/35 322 | f 43/6/39 44/7/40 41/4/37 323 | f 45/8/41 46/9/42 44/7/40 324 | f 47/10/43 48/11/44 45/8/41 325 | f 51/1/45 52/2/46 49/3/47 326 | f 53/4/48 54/5/49 52/2/46 327 | f 55/6/50 56/7/51 54/5/49 328 | f 57/8/52 58/9/53 56/7/51 329 | f 59/10/54 60/11/55 57/8/52 330 | f 63/1/56 64/2/57 61/3/58 331 | f 65/4/59 66/5/60 63/1/56 332 | f 67/6/61 68/7/62 66/5/60 333 | f 69/8/63 70/9/64 68/7/62 334 | f 71/10/65 72/11/66 69/8/63 335 | f 75/1/67 76/2/68 73/3/69 336 | f 77/4/70 78/5/71 76/2/68 337 | f 79/6/72 80/7/73 78/5/71 338 | f 81/8/74 82/9/75 80/7/73 339 | f 83/10/76 84/11/77 81/8/74 340 | f 87/1/78 88/2/79 85/3/80 341 | f 89/4/81 90/5/82 87/1/78 342 | f 91/6/83 92/7/84 90/5/82 343 | f 93/8/85 94/9/86 92/7/84 344 | f 95/10/87 96/11/88 93/8/85 345 | f 99/1/89 100/2/90 97/3/91 346 | f 101/4/92 102/5/93 99/1/89 347 | f 103/6/94 104/7/95 102/5/93 348 | f 105/8/96 106/9/97 104/7/95 349 | f 107/10/98 108/11/99 105/8/96 350 | f 111/1/100 112/2/101 110/12/102 351 | f 113/4/103 114/5/104 111/1/100 352 | f 115/6/105 116/7/106 114/5/104 353 | f 117/8/107 118/9/108 115/6/105 354 | f 119/10/109 120/11/110 118/9/108 355 | f 123/1/111 124/2/112 121/3/113 356 | f 125/4/114 126/5/115 123/1/111 357 | f 127/6/116 128/7/117 125/4/114 358 | f 129/8/118 130/9/119 127/6/116 359 | f 131/10/120 132/11/121 130/9/119 360 | f 135/1/122 136/2/123 134/12/124 361 | f 137/4/125 138/5/126 136/2/123 362 | f 139/6/127 140/7/128 137/4/125 363 | f 141/8/129 142/9/130 139/6/127 364 | f 143/10/131 144/11/132 142/9/130 365 | f 4/2/2 2/12/133 1/3/3 366 | f 6/5/5 4/2/2 3/1/1 367 | f 5/4/4 7/6/6 6/5/5 368 | f 10/9/9 8/7/7 7/6/6 369 | f 12/11/11 10/9/9 9/8/8 370 | f 13/3/134 15/1/12 14/12/14 371 | f 18/5/16 16/2/13 15/1/12 372 | f 20/7/18 18/5/16 17/4/15 373 | f 22/9/20 20/7/18 19/6/17 374 | f 21/8/19 23/10/21 22/9/20 375 | f 25/3/135 27/1/23 26/12/25 376 | f 27/1/23 29/4/26 28/2/24 377 | f 32/7/29 30/5/27 29/4/26 378 | f 34/9/31 32/7/29 31/6/28 379 | f 33/8/30 35/10/32 34/9/31 380 | f 40/2/35 38/12/136 37/3/36 381 | f 39/1/34 41/4/37 40/2/35 382 | f 44/7/40 42/5/38 41/4/37 383 | f 43/6/39 45/8/41 44/7/40 384 | f 48/11/44 46/9/42 45/8/41 385 | f 52/2/46 50/12/137 49/3/47 386 | f 51/1/45 53/4/48 52/2/46 387 | f 53/4/48 55/6/50 54/5/49 388 | f 55/6/50 57/8/52 56/7/51 389 | f 60/11/55 58/9/53 57/8/52 390 | f 64/2/57 62/12/138 61/3/58 391 | f 66/5/60 64/2/57 63/1/56 392 | f 65/4/59 67/6/61 66/5/60 393 | f 67/6/61 69/8/63 68/7/62 394 | f 72/11/66 70/9/64 69/8/63 395 | f 76/2/68 74/12/139 73/3/69 396 | f 75/1/67 77/4/70 76/2/68 397 | f 77/4/70 79/6/72 78/5/71 398 | f 79/6/72 81/8/74 80/7/73 399 | f 84/11/77 82/9/75 81/8/74 400 | f 88/2/79 86/12/140 85/3/80 401 | f 90/5/82 88/2/79 87/1/78 402 | f 89/4/81 91/6/83 90/5/82 403 | f 91/6/83 93/8/85 92/7/84 404 | f 96/11/88 94/9/86 93/8/85 405 | f 100/2/90 98/12/141 97/3/91 406 | f 102/5/93 100/2/90 99/1/89 407 | f 101/4/92 103/6/94 102/5/93 408 | f 103/6/94 105/8/96 104/7/95 409 | f 108/11/99 106/9/97 105/8/96 410 | f 109/3/142 111/1/100 110/12/102 411 | f 114/5/104 112/2/101 111/1/100 412 | f 113/4/103 115/6/105 114/5/104 413 | f 118/9/108 116/7/106 115/6/105 414 | f 117/8/107 119/10/109 118/9/108 415 | f 124/2/112 122/12/143 121/3/113 416 | f 126/5/115 124/2/112 123/1/111 417 | f 128/7/117 126/5/115 125/4/114 418 | f 130/9/119 128/7/117 127/6/116 419 | f 129/8/118 131/10/120 130/9/119 420 | f 133/3/144 135/1/122 134/12/124 421 | f 135/1/122 137/4/125 136/2/123 422 | f 140/7/128 138/5/126 137/4/125 423 | f 142/9/130 140/7/128 139/6/127 424 | f 141/8/129 143/10/131 142/9/130 425 | -------------------------------------------------------------------------------- /res/fern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/fern.png -------------------------------------------------------------------------------- /res/flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/flower.png -------------------------------------------------------------------------------- /res/front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/front.png -------------------------------------------------------------------------------- /res/grass.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.67 (sub 0) OBJ File: 'lowPolyPlants.blend' 2 | # www.blender.org 3 | mtllib grass.mtl 4 | o Plane 5 | v 0.063088 0.003610 -4.997082 6 | v -1.136912 0.003610 -4.997082 7 | v 0.063088 1.203610 -4.997082 8 | v -1.136912 1.203610 -4.997082 9 | v -0.536911 0.003610 -5.597082 10 | v -0.536912 0.003610 -4.397082 11 | v -0.536912 1.203610 -5.597083 12 | v -0.536912 1.203610 -4.397082 13 | v -5.427285 0.003610 -0.769423 14 | v -6.627285 0.003610 -0.769423 15 | v -5.427285 1.203610 -0.769424 16 | v -6.627285 1.203610 -0.769424 17 | v -6.027285 0.003610 -1.369424 18 | v -6.027285 0.003610 -0.169423 19 | v -6.027285 1.203610 -1.369424 20 | v -6.027285 1.203610 -0.169424 21 | v 0.627331 0.003610 1.154491 22 | v 0.120805 0.003610 0.066634 23 | v 0.627331 1.203610 1.154491 24 | v 0.120805 1.203610 0.066634 25 | v 0.917996 0.003610 0.357300 26 | v -0.169860 0.003611 0.863825 27 | v 0.917996 1.203610 0.357300 28 | v -0.169860 1.203610 0.863825 29 | v 2.736700 0.003610 -2.973755 30 | v 1.939363 0.003610 -3.870557 31 | v 2.736700 1.203610 -2.973755 32 | v 1.939363 1.203610 -3.870557 33 | v 2.786432 0.003610 -3.820825 34 | v 1.889630 0.003610 -3.023487 35 | v 2.786432 1.203610 -3.820825 36 | v 1.889630 1.203610 -3.023487 37 | v -2.374338 0.003610 -1.890785 38 | v -3.247929 0.003610 -2.713487 39 | v -2.374338 1.203610 -1.890785 40 | v -3.247929 1.203610 -2.713487 41 | v -2.399782 0.003610 -2.738931 42 | v -3.222484 0.003611 -1.865341 43 | v -2.399782 1.203610 -2.738931 44 | v -3.222484 1.203610 -1.865341 45 | v 6.729870 0.003610 2.758007 46 | v 7.206303 0.003610 1.656639 47 | v 6.729870 1.203610 2.758007 48 | v 7.206303 1.203610 1.656640 49 | v 7.518770 0.003610 2.445540 50 | v 6.417403 0.003611 1.969108 51 | v 7.518770 1.203610 2.445540 52 | v 6.417403 1.203610 1.969108 53 | v -2.949056 0.003611 6.270791 54 | v -2.019891 0.003611 5.511415 55 | v -2.949056 1.203610 6.270791 56 | v -2.019891 1.203610 5.511416 57 | v -2.104786 0.003610 6.355686 58 | v -2.864161 0.003611 5.426521 59 | v -2.104786 1.203610 6.355686 60 | v -2.864161 1.203610 5.426521 61 | v -11.257655 0.003611 -0.649311 62 | v -12.123328 0.003610 0.181718 63 | v -11.257655 1.203610 -0.649312 64 | v -12.123328 1.203610 0.181718 65 | v -12.106008 0.003611 -0.666633 66 | v -11.274976 0.003610 0.199040 67 | v -12.106008 1.203610 -0.666633 68 | v -11.274976 1.203610 0.199040 69 | v -5.115887 0.003611 6.717537 70 | v -5.981559 0.003611 7.548567 71 | v -5.115886 1.203610 6.717537 72 | v -5.981559 1.203610 7.548567 73 | v -5.964238 0.003611 6.700215 74 | v -5.133207 0.003611 7.565888 75 | v -5.964237 1.203610 6.700215 76 | v -5.133207 1.203610 7.565887 77 | v -4.044483 0.003611 4.351145 78 | v -5.163255 0.003611 3.917153 79 | v -4.044483 1.203610 4.351144 80 | v -5.163255 1.203610 3.917153 81 | v -4.386873 0.003611 3.574763 82 | v -4.820865 0.003611 4.693535 83 | v -4.386873 1.203610 3.574763 84 | v -4.820865 1.203610 4.693534 85 | v -5.924183 0.003610 -3.071747 86 | v -6.925926 0.003611 -3.732436 87 | v -5.924183 1.203610 -3.071747 88 | v -6.925926 1.203610 -3.732436 89 | v -6.094710 0.003611 -3.902963 90 | v -6.755400 0.003611 -2.901220 91 | v -6.094710 1.203610 -3.902963 92 | v -6.755400 1.203610 -2.901221 93 | v -7.753965 0.003611 1.248239 94 | v -8.950217 0.003611 1.153468 95 | v -7.753965 1.203610 1.248238 96 | v -8.950217 1.203610 1.153467 97 | v -8.304706 0.003611 0.602727 98 | v -8.399476 0.003611 1.798979 99 | v -8.304706 1.203610 0.602727 100 | v -8.399476 1.203610 1.798979 101 | v -1.912768 0.003610 0.464466 102 | v -2.331797 0.003611 -0.659996 103 | v -1.912768 1.203610 0.464466 104 | v -2.331796 1.203610 -0.659996 105 | v -1.560051 0.003611 -0.307279 106 | v -2.684512 0.003611 0.111750 107 | v -1.560051 1.203610 -0.307280 108 | v -2.684513 1.203610 0.111750 109 | v -4.742368 0.003611 1.656384 110 | v -5.161397 0.003611 0.531922 111 | v -4.742368 1.203610 1.656384 112 | v -5.161397 1.203610 0.531922 113 | v -4.389652 0.003611 0.884638 114 | v -5.514113 0.003611 1.303667 115 | v -4.389652 1.203610 0.884638 116 | v -5.514114 1.203610 1.303667 117 | v 4.391148 1.203610 0.926363 118 | v 3.597642 1.203610 0.026169 119 | v 4.391148 0.003611 0.926362 120 | v 3.597642 0.003610 0.026169 121 | v 3.544298 1.203610 0.873019 122 | v 4.444492 1.203610 0.079513 123 | v 3.544298 0.003610 0.873018 124 | v 4.444492 0.003610 0.079513 125 | v 4.806449 1.203610 3.812527 126 | v 3.732761 1.203610 3.276623 127 | v 4.806449 0.003611 3.812527 128 | v 3.732761 0.003611 3.276624 129 | v 4.001654 1.203610 4.081419 130 | v 4.537557 1.203610 3.007731 131 | v 4.001654 0.003611 4.081419 132 | v 4.537557 0.003611 3.007731 133 | v 6.609623 1.203610 -3.161592 134 | v 7.186171 1.203610 -4.214014 135 | v 6.609624 0.003611 -3.161592 136 | v 7.186171 0.003610 -4.214014 137 | v 6.371686 1.203610 -3.976077 138 | v 7.424108 1.203610 -3.399530 139 | v 6.371686 0.003611 -3.976076 140 | v 7.424108 0.003610 -3.399530 141 | v -0.487433 1.203610 1.980146 142 | v -1.577091 1.203610 1.477509 143 | v -0.487433 0.003611 1.980146 144 | v -1.577091 0.003610 1.477509 145 | v -1.283581 1.203610 2.273656 146 | v -0.780943 1.203610 1.183998 147 | v -1.283581 0.003610 2.273657 148 | v -0.780943 0.003610 1.183998 149 | v 10.179677 1.203610 0.517455 150 | v 8.984852 1.203610 0.406136 151 | v 10.179677 0.003611 0.517455 152 | v 8.984852 0.003610 0.406136 153 | v 9.526605 1.203610 1.059208 154 | v 9.637924 1.203610 -0.135617 155 | v 9.526605 0.003610 1.059208 156 | v 9.637924 0.003610 -0.135617 157 | v 5.869500 1.203610 5.422760 158 | v 4.930470 1.203610 6.169901 159 | v 5.869502 0.003611 5.422760 160 | v 4.930470 0.003611 6.169903 161 | v 5.773557 1.203610 6.265846 162 | v 5.026414 1.203610 5.326817 163 | v 5.773557 0.003611 6.265847 164 | v 5.026415 0.003611 5.326817 165 | v 0.637121 1.203610 -1.805795 166 | v 1.213668 1.203610 -2.858217 167 | v 0.637121 0.003611 -1.805795 168 | v 1.213669 0.003611 -2.858217 169 | v 0.399184 1.203610 -2.620279 170 | v 1.451606 1.203610 -2.043732 171 | v 0.399184 0.003611 -2.620279 172 | v 1.451606 0.003611 -2.043732 173 | v 1.740329 1.203610 -0.516481 174 | v 1.336903 1.203610 -1.646635 175 | v 1.740329 0.003611 -0.516482 176 | v 1.336903 0.003610 -1.646635 177 | v 0.973539 1.203610 -0.879845 178 | v 2.103693 1.203610 -1.283271 179 | v 0.973540 0.003611 -0.879845 180 | v 2.103693 0.003611 -1.283271 181 | v 3.117721 1.203610 2.883694 182 | v 2.804810 1.203610 1.725209 183 | v 3.117721 0.003611 2.883693 184 | v 2.804810 0.003611 1.725209 185 | v 2.382023 1.203610 2.460907 186 | v 3.540508 1.203610 2.147995 187 | v 2.382023 0.003611 2.460907 188 | v 3.540508 0.003611 2.147995 189 | v 1.243791 1.203610 8.964542 190 | v 0.077800 1.203610 9.248203 191 | v 1.243791 0.003611 8.964540 192 | v 0.077800 0.003611 9.248203 193 | v 0.802626 1.203610 9.689367 194 | v 0.518964 1.203610 8.523376 195 | v 0.802626 0.003611 9.689367 196 | v 0.518964 0.003611 8.523376 197 | v 4.819168 1.203610 -1.187724 198 | v 4.506256 1.203610 -2.346208 199 | v 4.819168 0.003611 -1.187724 200 | v 4.506257 0.003611 -2.346208 201 | v 4.083470 1.203610 -1.610511 202 | v 5.241954 1.203610 -1.923421 203 | v 4.083470 0.003611 -1.610510 204 | v 5.241954 0.003611 -1.923421 205 | v 0.499905 1.203610 -8.019167 206 | v -0.210803 1.203610 -8.986067 207 | v 0.499905 0.003610 -8.019167 208 | v -0.210803 0.003610 -8.986066 209 | v -0.338899 1.203610 -8.147264 210 | v 0.628001 1.203610 -8.857970 211 | v -0.338898 0.003610 -8.147264 212 | v 0.628001 0.003610 -8.857970 213 | v -2.017782 1.203610 3.719780 214 | v -2.953916 1.203610 2.969012 215 | v -2.017782 0.003611 3.719780 216 | v -2.953915 0.003611 2.969012 217 | v -2.861232 1.203610 3.812463 218 | v -2.110465 1.203610 2.876329 219 | v -2.861232 0.003611 3.812463 220 | v -2.110465 0.003611 2.876329 221 | v 1.450961 1.203610 5.045464 222 | v 0.268659 1.203610 4.840132 223 | v 1.450961 0.003611 5.045464 224 | v 0.268660 0.003611 4.840132 225 | v 0.757144 1.203610 5.533949 226 | v 0.962477 1.203610 4.351647 227 | v 0.757144 0.003611 5.533949 228 | v 0.962477 0.003611 4.351646 229 | vt 0.000100 0.000100 230 | vt 0.999900 0.000100 231 | vt 0.999900 0.999900 232 | vt 0.000100 0.999900 233 | usemtl Material.001 234 | s off 235 | f 2/1 1/2 3/3 4/4 236 | f 6/1 5/2 7/3 8/4 237 | f 10/1 9/2 11/3 12/4 238 | f 14/1 13/2 15/3 16/4 239 | f 18/1 17/2 19/3 20/4 240 | f 22/1 21/2 23/3 24/4 241 | f 26/1 25/2 27/3 28/4 242 | f 30/1 29/2 31/3 32/4 243 | f 34/1 33/2 35/3 36/4 244 | f 38/1 37/2 39/3 40/4 245 | f 42/1 41/2 43/3 44/4 246 | f 46/1 45/2 47/3 48/4 247 | f 50/1 49/2 51/3 52/4 248 | f 54/1 53/2 55/3 56/4 249 | f 58/1 57/2 59/3 60/4 250 | f 62/1 61/2 63/3 64/4 251 | f 66/1 65/2 67/3 68/4 252 | f 70/1 69/2 71/3 72/4 253 | f 74/1 73/2 75/3 76/4 254 | f 78/1 77/2 79/3 80/4 255 | f 82/1 81/2 83/3 84/4 256 | f 86/1 85/2 87/3 88/4 257 | f 90/1 89/2 91/3 92/4 258 | f 94/1 93/2 95/3 96/4 259 | f 98/1 97/2 99/3 100/4 260 | f 102/1 101/2 103/3 104/4 261 | f 106/1 105/2 107/3 108/4 262 | f 110/1 109/2 111/3 112/4 263 | f 115/1 116/2 114/3 113/4 264 | f 119/1 120/2 118/3 117/4 265 | f 123/1 124/2 122/3 121/4 266 | f 127/1 128/2 126/3 125/4 267 | f 131/1 132/2 130/3 129/4 268 | f 135/1 136/2 134/3 133/4 269 | f 139/1 140/2 138/3 137/4 270 | f 143/1 144/2 142/3 141/4 271 | f 147/1 148/2 146/3 145/4 272 | f 151/1 152/2 150/3 149/4 273 | f 155/1 156/2 154/3 153/4 274 | f 159/1 160/2 158/3 157/4 275 | f 163/1 164/2 162/3 161/4 276 | f 167/1 168/2 166/3 165/4 277 | f 171/1 172/2 170/3 169/4 278 | f 175/1 176/2 174/3 173/4 279 | f 179/1 180/2 178/3 177/4 280 | f 183/1 184/2 182/3 181/4 281 | f 187/1 188/2 186/3 185/4 282 | f 191/1 192/2 190/3 189/4 283 | f 195/1 196/2 194/3 193/4 284 | f 199/1 200/2 198/3 197/4 285 | f 203/1 204/2 202/3 201/4 286 | f 207/1 208/2 206/3 205/4 287 | f 211/1 212/2 210/3 209/4 288 | f 215/1 216/2 214/3 213/4 289 | f 219/1 220/2 218/3 217/4 290 | f 223/1 224/2 222/3 221/4 291 | f 1 4 292 | f 5 8 293 | f 9 12 294 | f 13 16 295 | f 180 177 296 | f 184 181 297 | f 17 20 298 | f 21 24 299 | f 25 28 300 | f 29 32 301 | f 33 36 302 | f 37 40 303 | f 41 44 304 | f 45 48 305 | f 49 52 306 | f 53 56 307 | f 57 60 308 | f 61 64 309 | f 65 68 310 | f 69 72 311 | f 196 193 312 | f 200 197 313 | f 73 76 314 | f 77 80 315 | f 81 84 316 | f 85 88 317 | f 89 92 318 | f 93 96 319 | f 97 100 320 | f 101 104 321 | f 105 108 322 | f 109 112 323 | f 204 201 324 | f 208 205 325 | f 188 185 326 | f 192 189 327 | f 120 117 328 | f 144 141 329 | f 152 149 330 | f 140 137 331 | f 164 161 332 | f 168 165 333 | f 136 133 334 | f 116 113 335 | f 148 145 336 | f 212 209 337 | f 216 213 338 | f 132 129 339 | f 124 121 340 | f 172 169 341 | f 176 173 342 | f 220 217 343 | f 224 221 344 | f 160 157 345 | f 128 125 346 | f 156 153 347 | -------------------------------------------------------------------------------- /res/grass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/grass.png -------------------------------------------------------------------------------- /res/grassFlowers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/grassFlowers.png -------------------------------------------------------------------------------- /res/grassModel.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.67 (sub 0) OBJ File: 'lowPolyPlants.blend' 2 | # www.blender.org 3 | o Plane 4 | v 0.063088 0.003610 -4.997082 5 | v -1.136912 0.003610 -4.997082 6 | v 0.063088 1.203610 -4.997082 7 | v -1.136912 1.203610 -4.997082 8 | v -0.536911 0.003610 -5.597082 9 | v -0.536912 0.003610 -4.397082 10 | v -0.536912 1.203610 -5.597083 11 | v -0.536912 1.203610 -4.397082 12 | v -5.427285 0.003610 -0.769423 13 | v -6.627285 0.003610 -0.769423 14 | v -5.427285 1.203610 -0.769424 15 | v -6.627285 1.203610 -0.769424 16 | v -6.027285 0.003610 -1.369424 17 | v -6.027285 0.003610 -0.169423 18 | v -6.027285 1.203610 -1.369424 19 | v -6.027285 1.203610 -0.169424 20 | v 0.627331 0.003610 1.154491 21 | v 0.120805 0.003610 0.066634 22 | v 0.627331 1.203610 1.154491 23 | v 0.120805 1.203610 0.066634 24 | v 0.917996 0.003610 0.357300 25 | v -0.169860 0.003611 0.863825 26 | v 0.917996 1.203610 0.357300 27 | v -0.169860 1.203610 0.863825 28 | v 2.736700 0.003610 -2.973755 29 | v 1.939363 0.003610 -3.870557 30 | v 2.736700 1.203610 -2.973755 31 | v 1.939363 1.203610 -3.870557 32 | v 2.786432 0.003610 -3.820825 33 | v 1.889630 0.003610 -3.023487 34 | v 2.786432 1.203610 -3.820825 35 | v 1.889630 1.203610 -3.023487 36 | v -2.374338 0.003610 -1.890785 37 | v -3.247929 0.003610 -2.713487 38 | v -2.374338 1.203610 -1.890785 39 | v -3.247929 1.203610 -2.713487 40 | v -2.399782 0.003610 -2.738931 41 | v -3.222484 0.003611 -1.865341 42 | v -2.399782 1.203610 -2.738931 43 | v -3.222484 1.203610 -1.865341 44 | v 6.729870 0.003610 2.758007 45 | v 7.206303 0.003610 1.656639 46 | v 6.729870 1.203610 2.758007 47 | v 7.206303 1.203610 1.656640 48 | v 7.518770 0.003610 2.445540 49 | v 6.417403 0.003611 1.969108 50 | v 7.518770 1.203610 2.445540 51 | v 6.417403 1.203610 1.969108 52 | v -2.949056 0.003611 6.270791 53 | v -2.019891 0.003611 5.511415 54 | v -2.949056 1.203610 6.270791 55 | v -2.019891 1.203610 5.511416 56 | v -2.104786 0.003610 6.355686 57 | v -2.864161 0.003611 5.426521 58 | v -2.104786 1.203610 6.355686 59 | v -2.864161 1.203610 5.426521 60 | v -11.257655 0.003611 -0.649311 61 | v -12.123328 0.003610 0.181718 62 | v -11.257655 1.203610 -0.649312 63 | v -12.123328 1.203610 0.181718 64 | v -12.106008 0.003611 -0.666633 65 | v -11.274976 0.003610 0.199040 66 | v -12.106008 1.203610 -0.666633 67 | v -11.274976 1.203610 0.199040 68 | v -5.115887 0.003611 6.717537 69 | v -5.981559 0.003611 7.548567 70 | v -5.115886 1.203610 6.717537 71 | v -5.981559 1.203610 7.548567 72 | v -5.964238 0.003611 6.700215 73 | v -5.133207 0.003611 7.565888 74 | v -5.964237 1.203610 6.700215 75 | v -5.133207 1.203610 7.565887 76 | v -4.044483 0.003611 4.351145 77 | v -5.163255 0.003611 3.917153 78 | v -4.044483 1.203610 4.351144 79 | v -5.163255 1.203610 3.917153 80 | v -4.386873 0.003611 3.574763 81 | v -4.820865 0.003611 4.693535 82 | v -4.386873 1.203610 3.574763 83 | v -4.820865 1.203610 4.693534 84 | v -5.924183 0.003610 -3.071747 85 | v -6.925926 0.003611 -3.732436 86 | v -5.924183 1.203610 -3.071747 87 | v -6.925926 1.203610 -3.732436 88 | v -6.094710 0.003611 -3.902963 89 | v -6.755400 0.003611 -2.901220 90 | v -6.094710 1.203610 -3.902963 91 | v -6.755400 1.203610 -2.901221 92 | v -7.753965 0.003611 1.248239 93 | v -8.950217 0.003611 1.153468 94 | v -7.753965 1.203610 1.248238 95 | v -8.950217 1.203610 1.153467 96 | v -8.304706 0.003611 0.602727 97 | v -8.399476 0.003611 1.798979 98 | v -8.304706 1.203610 0.602727 99 | v -8.399476 1.203610 1.798979 100 | v -1.912768 0.003610 0.464466 101 | v -2.331797 0.003611 -0.659996 102 | v -1.912768 1.203610 0.464466 103 | v -2.331796 1.203610 -0.659996 104 | v -1.560051 0.003611 -0.307279 105 | v -2.684512 0.003611 0.111750 106 | v -1.560051 1.203610 -0.307280 107 | v -2.684513 1.203610 0.111750 108 | v -4.742368 0.003611 1.656384 109 | v -5.161397 0.003611 0.531922 110 | v -4.742368 1.203610 1.656384 111 | v -5.161397 1.203610 0.531922 112 | v -4.389652 0.003611 0.884638 113 | v -5.514113 0.003611 1.303667 114 | v -4.389652 1.203610 0.884638 115 | v -5.514114 1.203610 1.303667 116 | v 4.391148 1.203610 0.926363 117 | v 3.597642 1.203610 0.026169 118 | v 4.391148 0.003611 0.926362 119 | v 3.597642 0.003610 0.026169 120 | v 3.544298 1.203610 0.873019 121 | v 4.444492 1.203610 0.079513 122 | v 3.544298 0.003610 0.873018 123 | v 4.444492 0.003610 0.079513 124 | v 4.806449 1.203610 3.812527 125 | v 3.732761 1.203610 3.276623 126 | v 4.806449 0.003611 3.812527 127 | v 3.732761 0.003611 3.276624 128 | v 4.001654 1.203610 4.081419 129 | v 4.537557 1.203610 3.007731 130 | v 4.001654 0.003611 4.081419 131 | v 4.537557 0.003611 3.007731 132 | v 6.609623 1.203610 -3.161592 133 | v 7.186171 1.203610 -4.214014 134 | v 6.609624 0.003611 -3.161592 135 | v 7.186171 0.003610 -4.214014 136 | v 6.371686 1.203610 -3.976077 137 | v 7.424108 1.203610 -3.399530 138 | v 6.371686 0.003611 -3.976076 139 | v 7.424108 0.003610 -3.399530 140 | v -0.487433 1.203610 1.980146 141 | v -1.577091 1.203610 1.477509 142 | v -0.487433 0.003611 1.980146 143 | v -1.577091 0.003610 1.477509 144 | v -1.283581 1.203610 2.273656 145 | v -0.780943 1.203610 1.183998 146 | v -1.283581 0.003610 2.273657 147 | v -0.780943 0.003610 1.183998 148 | v 10.179677 1.203610 0.517455 149 | v 8.984852 1.203610 0.406136 150 | v 10.179677 0.003611 0.517455 151 | v 8.984852 0.003610 0.406136 152 | v 9.526605 1.203610 1.059208 153 | v 9.637924 1.203610 -0.135617 154 | v 9.526605 0.003610 1.059208 155 | v 9.637924 0.003610 -0.135617 156 | v 5.869500 1.203610 5.422760 157 | v 4.930470 1.203610 6.169901 158 | v 5.869502 0.003611 5.422760 159 | v 4.930470 0.003611 6.169903 160 | v 5.773557 1.203610 6.265846 161 | v 5.026414 1.203610 5.326817 162 | v 5.773557 0.003611 6.265847 163 | v 5.026415 0.003611 5.326817 164 | v 0.637121 1.203610 -1.805795 165 | v 1.213668 1.203610 -2.858217 166 | v 0.637121 0.003611 -1.805795 167 | v 1.213669 0.003611 -2.858217 168 | v 0.399184 1.203610 -2.620279 169 | v 1.451606 1.203610 -2.043732 170 | v 0.399184 0.003611 -2.620279 171 | v 1.451606 0.003611 -2.043732 172 | v 1.740329 1.203610 -0.516481 173 | v 1.336903 1.203610 -1.646635 174 | v 1.740329 0.003611 -0.516482 175 | v 1.336903 0.003610 -1.646635 176 | v 0.973539 1.203610 -0.879845 177 | v 2.103693 1.203610 -1.283271 178 | v 0.973540 0.003611 -0.879845 179 | v 2.103693 0.003611 -1.283271 180 | v 3.117721 1.203610 2.883694 181 | v 2.804810 1.203610 1.725209 182 | v 3.117721 0.003611 2.883693 183 | v 2.804810 0.003611 1.725209 184 | v 2.382023 1.203610 2.460907 185 | v 3.540508 1.203610 2.147995 186 | v 2.382023 0.003611 2.460907 187 | v 3.540508 0.003611 2.147995 188 | v 1.243791 1.203610 8.964542 189 | v 0.077800 1.203610 9.248203 190 | v 1.243791 0.003611 8.964540 191 | v 0.077800 0.003611 9.248203 192 | v 0.802626 1.203610 9.689367 193 | v 0.518964 1.203610 8.523376 194 | v 0.802626 0.003611 9.689367 195 | v 0.518964 0.003611 8.523376 196 | v 4.819168 1.203610 -1.187724 197 | v 4.506256 1.203610 -2.346208 198 | v 4.819168 0.003611 -1.187724 199 | v 4.506257 0.003611 -2.346208 200 | v 4.083470 1.203610 -1.610511 201 | v 5.241954 1.203610 -1.923421 202 | v 4.083470 0.003611 -1.610510 203 | v 5.241954 0.003611 -1.923421 204 | v 0.499905 1.203610 -8.019167 205 | v -0.210803 1.203610 -8.986067 206 | v 0.499905 0.003610 -8.019167 207 | v -0.210803 0.003610 -8.986066 208 | v -0.338899 1.203610 -8.147264 209 | v 0.628001 1.203610 -8.857970 210 | v -0.338898 0.003610 -8.147264 211 | v 0.628001 0.003610 -8.857970 212 | v -2.017782 1.203610 3.719780 213 | v -2.953916 1.203610 2.969012 214 | v -2.017782 0.003611 3.719780 215 | v -2.953915 0.003611 2.969012 216 | v -2.861232 1.203610 3.812463 217 | v -2.110465 1.203610 2.876329 218 | v -2.861232 0.003611 3.812463 219 | v -2.110465 0.003611 2.876329 220 | v 1.450961 1.203610 5.045464 221 | v 0.268659 1.203610 4.840132 222 | v 1.450961 0.003611 5.045464 223 | v 0.268660 0.003611 4.840132 224 | v 0.757144 1.203610 5.533949 225 | v 0.962477 1.203610 4.351647 226 | v 0.757144 0.003611 5.533949 227 | v 0.962477 0.003611 4.351646 228 | vt 0.000100 0.000100 229 | vt 0.999900 0.000100 230 | vt 0.999900 0.999900 231 | vt 0.000100 0.999900 232 | vn 0.000000 0.000000 1.000000 233 | vn 1.000000 0.000000 0.000000 234 | vn -0.906547 0.000000 0.422104 235 | vn 0.422104 0.000000 0.906547 236 | vn -0.747335 0.000000 0.664448 237 | vn 0.664448 0.000000 0.747335 238 | vn -0.685585 0.000000 0.727992 239 | vn 0.727992 0.000000 0.685585 240 | vn -0.917807 0.000001 -0.397027 241 | vn -0.397027 0.000000 0.917807 242 | vn -0.632813 0.000000 -0.774304 243 | vn -0.774305 0.000000 0.632813 244 | vn 0.692525 0.000000 0.721394 245 | vn 0.721393 -0.000000 -0.692526 246 | vn 0.721394 -0.000001 -0.692525 247 | vn -0.361660 0.000000 0.932310 248 | vn 0.932310 0.000000 0.361660 249 | vn -0.550575 0.000000 0.834786 250 | vn 0.834786 0.000000 0.550575 251 | vn -0.078976 0.000000 0.996877 252 | vn 0.996877 0.000000 0.078975 253 | vn -0.937052 0.000000 0.349191 254 | vn 0.349191 0.000001 0.937052 255 | vn 0.349191 -0.000000 0.937052 256 | vn 0.750161 0.000000 -0.661255 257 | vn 0.661255 -0.000000 0.750162 258 | vn 0.446586 -0.000000 -0.894741 259 | vn 0.894741 -0.000000 0.446586 260 | vn 0.877019 0.000000 0.480456 261 | vn -0.480456 0.000001 0.877019 262 | vn 0.418865 -0.000000 -0.908049 263 | vn 0.908049 0.000000 0.418865 264 | vn 0.092766 0.000000 -0.995688 265 | vn 0.995688 0.000000 0.092766 266 | vn -0.622618 -0.000001 -0.782526 267 | vn 0.782526 0.000001 -0.622618 268 | vn -0.480456 0.000000 0.877019 269 | vn 0.941795 -0.000000 -0.336188 270 | vn 0.336188 0.000000 0.941795 271 | vn 0.965404 -0.000000 -0.260759 272 | vn 0.260759 0.000000 0.965404 273 | vn -0.236386 0.000001 -0.971659 274 | vn 0.971659 -0.000000 -0.236386 275 | vn 0.965404 0.000001 -0.260759 276 | vn 0.260760 0.000000 0.965404 277 | vn 0.805749 -0.000000 -0.592257 278 | vn 0.592256 -0.000000 0.805750 279 | vn 0.625641 0.000001 -0.780111 280 | vn 0.780112 0.000000 0.625640 281 | vn 0.171110 0.000000 -0.985252 282 | vn 0.985252 0.000000 0.171111 283 | vn 0.664448 0.000000 0.747334 284 | vn -0.917807 -0.000000 -0.397028 285 | vn -0.632813 -0.000000 -0.774305 286 | vn -0.774304 0.000000 0.632813 287 | vn 0.721394 -0.000000 -0.692525 288 | vn -0.361659 0.000000 0.932310 289 | vn 0.661254 -0.000000 0.750162 290 | vn 0.877019 0.000001 0.480457 291 | vn 0.092765 -0.000000 -0.995688 292 | vn -0.622618 -0.000000 -0.782526 293 | vn 0.782525 -0.000000 -0.622619 294 | vn -0.236384 0.000000 -0.971660 295 | vn 0.971659 0.000000 -0.236385 296 | vn 0.965404 0.000000 -0.260760 297 | vn 0.260759 0.000001 0.965404 298 | vn 0.805750 0.000000 -0.592256 299 | vn 0.625640 -0.000000 -0.780112 300 | vn 0.780112 0.000000 0.625639 301 | s off 302 | f 2/1/1 1/2/1 3/3/1 303 | f 6/1/2 5/2/2 7/3/2 304 | f 10/1/1 9/2/1 11/3/1 305 | f 14/1/2 13/2/2 15/3/2 306 | f 18/1/3 17/2/3 20/4/3 307 | f 22/1/4 21/2/4 23/3/4 308 | f 26/1/5 25/2/5 28/4/5 309 | f 30/1/6 29/2/6 31/3/6 310 | f 34/1/7 33/2/7 36/4/7 311 | f 38/1/8 37/2/8 39/3/8 312 | f 42/1/9 41/2/9 44/4/9 313 | f 46/1/10 45/2/10 48/4/10 314 | f 50/1/11 49/2/11 52/4/11 315 | f 54/1/12 53/2/12 56/4/12 316 | f 58/1/13 57/2/13 59/3/13 317 | f 62/1/14 61/2/14 63/3/14 318 | f 66/1/13 65/2/13 67/3/13 319 | f 70/1/15 69/2/15 71/3/15 320 | f 74/1/16 73/2/16 76/4/16 321 | f 78/1/17 77/2/17 79/3/17 322 | f 82/1/18 81/2/18 84/4/18 323 | f 86/1/19 85/2/19 87/3/19 324 | f 90/1/20 89/2/20 92/4/20 325 | f 94/1/21 93/2/21 95/3/21 326 | f 98/1/22 97/2/22 100/4/22 327 | f 102/1/23 101/2/23 103/3/23 328 | f 106/1/22 105/2/22 108/4/22 329 | f 110/1/24 109/2/24 111/3/24 330 | f 115/1/25 116/2/25 114/3/25 331 | f 119/1/26 120/2/26 118/3/26 332 | f 123/1/27 124/2/27 122/3/27 333 | f 127/1/28 128/2/28 126/3/28 334 | f 131/1/29 132/2/29 130/3/29 335 | f 135/1/30 136/2/30 133/4/30 336 | f 139/1/31 140/2/31 138/3/31 337 | f 143/1/32 144/2/32 142/3/32 338 | f 147/1/33 148/2/33 146/3/33 339 | f 151/1/34 152/2/34 150/3/34 340 | f 155/1/35 156/2/35 153/4/35 341 | f 159/1/36 160/2/36 158/3/36 342 | f 163/1/29 164/2/29 162/3/29 343 | f 167/1/37 168/2/37 165/4/37 344 | f 171/1/38 172/2/38 170/3/38 345 | f 175/1/39 176/2/39 174/3/39 346 | f 179/1/40 180/2/40 178/3/40 347 | f 183/1/41 184/2/41 182/3/41 348 | f 187/1/42 188/2/42 185/4/42 349 | f 191/1/43 192/2/43 190/3/43 350 | f 195/1/44 196/2/44 194/3/44 351 | f 199/1/45 200/2/45 198/3/45 352 | f 203/1/46 204/2/46 202/3/46 353 | f 207/1/47 208/2/47 206/3/47 354 | f 211/1/48 212/2/48 210/3/48 355 | f 215/1/49 216/2/49 214/3/49 356 | f 219/1/50 220/2/50 218/3/50 357 | f 223/1/51 224/2/51 222/3/51 358 | f 4/4/1 2/1/1 3/3/1 359 | f 8/4/2 6/1/2 7/3/2 360 | f 12/4/1 10/1/1 11/3/1 361 | f 16/4/2 14/1/2 15/3/2 362 | f 17/2/3 19/3/3 20/4/3 363 | f 24/4/4 22/1/4 23/3/4 364 | f 25/2/5 27/3/5 28/4/5 365 | f 32/4/52 30/1/52 31/3/52 366 | f 33/2/7 35/3/7 36/4/7 367 | f 40/4/8 38/1/8 39/3/8 368 | f 41/2/53 43/3/53 44/4/53 369 | f 45/2/10 47/3/10 48/4/10 370 | f 49/2/54 51/3/54 52/4/54 371 | f 53/2/55 55/3/55 56/4/55 372 | f 60/4/13 58/1/13 59/3/13 373 | f 64/4/14 62/1/14 63/3/14 374 | f 68/4/13 66/1/13 67/3/13 375 | f 72/4/56 70/1/56 71/3/56 376 | f 73/2/57 75/3/57 76/4/57 377 | f 80/4/17 78/1/17 79/3/17 378 | f 81/2/18 83/3/18 84/4/18 379 | f 88/4/19 86/1/19 87/3/19 380 | f 89/2/20 91/3/20 92/4/20 381 | f 96/4/21 94/1/21 95/3/21 382 | f 97/2/22 99/3/22 100/4/22 383 | f 104/4/24 102/1/24 103/3/24 384 | f 105/2/22 107/3/22 108/4/22 385 | f 112/4/24 110/1/24 111/3/24 386 | f 113/4/25 115/1/25 114/3/25 387 | f 117/4/58 119/1/58 118/3/58 388 | f 121/4/27 123/1/27 122/3/27 389 | f 125/4/28 127/1/28 126/3/28 390 | f 129/4/59 131/1/59 130/3/59 391 | f 136/2/37 134/3/37 133/4/37 392 | f 137/4/31 139/1/31 138/3/31 393 | f 141/4/32 143/1/32 142/3/32 394 | f 145/4/60 147/1/60 146/3/60 395 | f 149/4/34 151/1/34 150/3/34 396 | f 156/2/61 154/3/61 153/4/61 397 | f 157/4/62 159/1/62 158/3/62 398 | f 161/4/29 163/1/29 162/3/29 399 | f 168/2/37 166/3/37 165/4/37 400 | f 169/4/38 171/1/38 170/3/38 401 | f 173/4/39 175/1/39 174/3/39 402 | f 177/4/40 179/1/40 178/3/40 403 | f 181/4/45 183/1/45 182/3/45 404 | f 188/2/63 186/3/63 185/4/63 405 | f 189/4/64 191/1/64 190/3/64 406 | f 193/4/65 195/1/65 194/3/65 407 | f 197/4/66 199/1/66 198/3/66 408 | f 201/4/67 203/1/67 202/3/67 409 | f 205/4/47 207/1/47 206/3/47 410 | f 209/4/68 211/1/68 210/3/68 411 | f 213/4/69 215/1/69 214/3/69 412 | f 217/4/50 219/1/50 218/3/50 413 | f 221/4/51 223/1/51 222/3/51 414 | -------------------------------------------------------------------------------- /res/grassTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/grassTexture.png -------------------------------------------------------------------------------- /res/grassy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/grassy.png -------------------------------------------------------------------------------- /res/health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/health.png -------------------------------------------------------------------------------- /res/heightmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/heightmap.png -------------------------------------------------------------------------------- /res/lamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/lamp.png -------------------------------------------------------------------------------- /res/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/left.png -------------------------------------------------------------------------------- /res/lowPolyTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/lowPolyTree.png -------------------------------------------------------------------------------- /res/matchingNormalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/matchingNormalMap.png -------------------------------------------------------------------------------- /res/mud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/mud.png -------------------------------------------------------------------------------- /res/nightBack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightBack.png -------------------------------------------------------------------------------- /res/nightBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightBottom.png -------------------------------------------------------------------------------- /res/nightFront.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightFront.png -------------------------------------------------------------------------------- /res/nightLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightLeft.png -------------------------------------------------------------------------------- /res/nightRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightRight.png -------------------------------------------------------------------------------- /res/nightTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/nightTop.png -------------------------------------------------------------------------------- /res/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/normal.png -------------------------------------------------------------------------------- /res/normalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/normalMap.png -------------------------------------------------------------------------------- /res/path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/path.png -------------------------------------------------------------------------------- /res/pinkFlowers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/pinkFlowers.png -------------------------------------------------------------------------------- /res/playerTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/playerTexture.png -------------------------------------------------------------------------------- /res/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/right.png -------------------------------------------------------------------------------- /res/stallTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/stallTexture.png -------------------------------------------------------------------------------- /res/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/top.png -------------------------------------------------------------------------------- /res/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/tree.png -------------------------------------------------------------------------------- /res/waterDUDV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/waterDUDV.png -------------------------------------------------------------------------------- /res/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/res/white.png -------------------------------------------------------------------------------- /src/camera.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "camera.hpp" 3 | 4 | #include "player.hpp" 5 | 6 | #include "SDL.h" 7 | 8 | #include 9 | 10 | namespace { 11 | 12 | constexpr float to_radians(float degrees) 13 | { 14 | return degrees * M_PI/180.0; 15 | } 16 | 17 | } 18 | 19 | namespace jac { 20 | 21 | void camera::move() 22 | { 23 | calculate_zoom(); 24 | calculate_pitch(); 25 | calculate_angle_around_player(); 26 | float horizontal_distance = calculate_horizontal_distance(); 27 | float vertical_distance = calculate_vertical_distance(); 28 | calculate_camera_position(horizontal_distance, vertical_distance); 29 | yaw = 180 - (player_.get_rot_y() + angle_around_player); 30 | } 31 | 32 | camera::camera(const player& player_) 33 | : player_{player_} 34 | {} 35 | 36 | const glm::vec3& camera::get_position() const 37 | { 38 | return position; 39 | } 40 | 41 | float camera::get_pitch() const 42 | { 43 | return pitch; 44 | } 45 | 46 | float camera::get_yaw() const 47 | { 48 | return yaw; 49 | } 50 | 51 | float camera::get_roll() const 52 | { 53 | return roll; 54 | } 55 | 56 | float camera::calculate_horizontal_distance() 57 | { 58 | return distance_from_player * std::cos(to_radians(pitch)); 59 | } 60 | 61 | float camera::calculate_vertical_distance() 62 | { 63 | return distance_from_player * std::sin(to_radians(pitch)); 64 | } 65 | 66 | void camera::calculate_camera_position(float horiz_distance, 67 | float vert_distance) 68 | { 69 | float theta = player_.get_rot_y() + angle_around_player; 70 | float offset_x = horiz_distance * std::sin(to_radians(theta)); 71 | float offset_z = horiz_distance * std::cos(to_radians(theta)); 72 | position.x = player_.get_position().x - offset_x; 73 | position.y = player_.get_position().y + vert_distance; 74 | position.z = player_.get_position().z - offset_z; 75 | } 76 | 77 | void camera::calculate_zoom() 78 | { 79 | float zoom_level = mouse_wheel_delta; 80 | distance_from_player -= zoom_level; 81 | mouse_wheel_delta = 0; 82 | } 83 | 84 | void camera::mouse_wheel(int delta) 85 | { 86 | mouse_wheel_delta = delta; 87 | } 88 | 89 | void camera::calculate_pitch() 90 | { 91 | if (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON_RMASK) { 92 | float pitch_change = mouse_y_delta; 93 | pitch += pitch_change; 94 | mouse_y_delta = 0; 95 | } 96 | } 97 | 98 | void camera::calculate_angle_around_player() 99 | { 100 | if (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON_LMASK) { 101 | float angle_change = mouse_x_delta; 102 | angle_around_player -= angle_change; 103 | mouse_x_delta = 0; 104 | } 105 | } 106 | 107 | void camera::mouse_move(int dx, int dy) 108 | { 109 | mouse_x_delta = 0.3 * dx; 110 | mouse_y_delta = 0.1 * dy; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/camera.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_CAMERA_HPP 2 | #define JAC_CAMERA_HPP 3 | 4 | #include 5 | 6 | namespace jac { 7 | 8 | class player; 9 | 10 | class camera { 11 | public: 12 | camera(const player& player); 13 | 14 | const glm::vec3& get_position() const; 15 | void set_position(const glm::vec3& pos) { position = pos; } 16 | float get_pitch() const; 17 | float get_yaw() const; 18 | float get_roll() const; 19 | void move(); 20 | void mouse_wheel(int delta); 21 | void mouse_move(int dx, int dy); 22 | void invert_pitch() { pitch = -pitch; } 23 | 24 | private: 25 | void calculate_zoom(); 26 | void calculate_pitch(); 27 | void calculate_angle_around_player(); 28 | float calculate_horizontal_distance(); 29 | float calculate_vertical_distance(); 30 | 31 | const player& player_; 32 | glm::vec3 position{100.0f, 35.0f, 50.0f}; 33 | float pitch = 25.0f; 34 | float yaw = 0.0f; 35 | float roll = 0.0f; 36 | float distance_from_player = 50.0f; 37 | float angle_around_player = 0; 38 | 39 | int mouse_wheel_delta = 0; 40 | int mouse_x_delta = 0; 41 | int mouse_y_delta = 0; 42 | 43 | void calculate_camera_position(float horiz_distance, float vert_distance); 44 | }; 45 | 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/display_manager.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "display_manager.hpp" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace { 9 | 10 | const char* get_gl_error(GLenum err) 11 | { 12 | switch (err) { 13 | case GL_INVALID_ENUM: 14 | return "invalid enum"; 15 | case GL_INVALID_VALUE: 16 | return "invalid value"; 17 | case GL_INVALID_OPERATION: 18 | return "invalid Operation"; 19 | case GL_INVALID_FRAMEBUFFER_OPERATION: 20 | return "invalid framebuffer operation"; 21 | case GL_OUT_OF_MEMORY: 22 | return "out of memory"; 23 | default: 24 | return "unknown"; 25 | } 26 | } 27 | 28 | extern "C" 29 | void error_check_callback(const char* name, void* /*funcptr*/, 30 | int /*len_args*/, ...) 31 | { 32 | GLenum err = GL_NO_ERROR; 33 | 34 | while ((err = glad_glGetError()) != GL_NO_ERROR) { 35 | const char* msg = get_gl_error(err); 36 | SDL_Log("Got GL error \"%s\" in %s", msg, name); 37 | SDL_assert(err == GL_NO_ERROR); 38 | } 39 | } 40 | 41 | // For the record, I deeply object to these global variables 42 | static jac::time_point last_frame_time; 43 | static jac::seconds delta; 44 | 45 | } 46 | 47 | namespace jac { 48 | 49 | constexpr int width = 1280; 50 | constexpr int height = 720; 51 | 52 | display create_display() 53 | { 54 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 55 | SDL_GL_CONTEXT_PROFILE_CORE); 56 | 57 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 58 | SDL_GL_CONTEXT_DEBUG_FLAG | 59 | SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 60 | 61 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 62 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 63 | 64 | auto* window = SDL_CreateWindow("Jac", SDL_WINDOWPOS_UNDEFINED, 65 | SDL_WINDOWPOS_UNDEFINED, 66 | width, height, 67 | SDL_WINDOW_OPENGL | 68 | SDL_WINDOW_RESIZABLE); 69 | 70 | auto ctx = SDL_GL_CreateContext(window); 71 | 72 | SDL_GL_SetSwapInterval(1); 73 | 74 | gladLoadGLLoader(SDL_GL_GetProcAddress); 75 | 76 | glad_set_post_callback(error_check_callback); 77 | 78 | { 79 | int w, h; 80 | SDL_GL_GetDrawableSize(window, &w, &h); 81 | glViewport(0, 0, w, h); 82 | } 83 | 84 | last_frame_time = std::chrono::high_resolution_clock::now(); 85 | 86 | return { sdl_window_ptr(window), sdl_gl_context{ctx} }; 87 | } 88 | 89 | jac::seconds get_frame_time_seconds() 90 | { 91 | return delta; 92 | } 93 | 94 | void update_display(display& display) 95 | { 96 | SDL_GL_SwapWindow(display.window.get()); 97 | auto current_frame_time = std::chrono::high_resolution_clock::now(); 98 | delta = current_frame_time - last_frame_time; 99 | last_frame_time = current_frame_time; 100 | } 101 | 102 | 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/display_manager.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_DISPLAY_MANAGER_HPP 2 | #define JAC_DISPLAY_MANAGER_HPP 3 | 4 | #include "sdl_handles.hpp" 5 | 6 | #include 7 | 8 | namespace jac { 9 | 10 | using time_point = std::chrono::high_resolution_clock::time_point; 11 | using seconds = std::chrono::duration; 12 | 13 | struct display { 14 | sdl_window_ptr window; 15 | sdl_gl_context gl_context; 16 | }; 17 | 18 | display create_display(); 19 | 20 | void update_display(display& display); 21 | 22 | seconds get_frame_time_seconds(); 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/entity.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "entity.hpp" 3 | #include "textured_model.hpp" 4 | 5 | namespace jac { 6 | 7 | void entity::increase_position(float dx, float dy, float dz) 8 | { 9 | position += glm::vec3(dx, dy, dz); 10 | } 11 | 12 | void entity::increase_rotation(float dx, float dy, float dz) 13 | { 14 | rot_x += dx; 15 | rot_y += dy; 16 | rot_z += dz; 17 | } 18 | 19 | float entity::get_texture_x_offset() const 20 | { 21 | int column = texture_index % model.texture.number_of_rows; 22 | return column/(float)model.texture.number_of_rows; 23 | } 24 | 25 | float entity::get_texture_y_offset() const 26 | { 27 | int row = texture_index/model.texture.number_of_rows; 28 | return row/(float)model.texture.number_of_rows; 29 | } 30 | 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/entity.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_ENTITY_HPP 2 | #define JAC_ENTITY_HPP 3 | 4 | #include "textured_model.hpp" 5 | 6 | #include 7 | 8 | namespace jac { 9 | 10 | class entity { 11 | public: 12 | entity(const textured_model &model, const glm::vec3 &position, float rot_x, 13 | float rot_y, float rot_z, float scale) 14 | : model(model), 15 | position(position), 16 | rot_x(rot_x), rot_y(rot_y), 17 | rot_z(rot_z), 18 | scale(scale) 19 | {} 20 | 21 | entity(const textured_model &model, int index, 22 | const glm::vec3 &position, float rot_x, 23 | float rot_y, float rot_z, float scale) 24 | : model(model), 25 | position(position), 26 | rot_x(rot_x), rot_y(rot_y), 27 | rot_z(rot_z), 28 | scale(scale), 29 | texture_index(index) 30 | {} 31 | 32 | void increase_position(float dx, float dy, float dz); 33 | void increase_rotation(float dx, float dy, float dz); 34 | 35 | const textured_model& get_model() const { return model; } 36 | const glm::vec3& get_position() const { return position; } 37 | float get_rot_x() const { return rot_x; } 38 | float get_rot_y() const { return rot_y; } 39 | float get_rot_z() const { return rot_z; } 40 | float get_scale() const { return scale; } 41 | float get_texture_x_offset() const; 42 | float get_texture_y_offset() const; 43 | 44 | protected: 45 | textured_model model{}; 46 | glm::vec3 position{}; 47 | float rot_x = 0.0f; 48 | float rot_y = 0.0f; 49 | float rot_z = 0.0f; 50 | float scale = 0.0f; 51 | 52 | private: 53 | int texture_index = 0; 54 | }; 55 | 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/entity_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "entity_renderer.hpp" 3 | 4 | #include "entity.hpp" 5 | #include "master_renderer.hpp" 6 | #include "maths.hpp" 7 | #include "static_shader.hpp" 8 | #include "textured_model.hpp" 9 | 10 | #include "SDL.h" 11 | 12 | #include 13 | 14 | namespace jac { 15 | 16 | void entity_renderer::prepare_textured_model(const jac::textured_model& model) const 17 | { 18 | const auto& raw_model = model.raw; 19 | glBindVertexArray(raw_model.vao_id); 20 | glEnableVertexAttribArray(0); 21 | glEnableVertexAttribArray(1); 22 | glEnableVertexAttribArray(2); 23 | const auto& texture = model.texture; 24 | shader.load_number_of_rows(model.texture.number_of_rows); 25 | if (texture.has_transparency) { 26 | master_renderer::disable_culling(); 27 | } 28 | shader.load_fake_lighting_variable(texture.use_fake_lighting); 29 | shader.load_shine_variables(texture.shine_damper, texture.reflectivity); 30 | glActiveTexture(GL_TEXTURE0); 31 | glBindTexture(GL_TEXTURE_2D, model.texture.texture_id); 32 | } 33 | 34 | void entity_renderer::prepare_instance(const entity& entity) const 35 | { 36 | glm::mat4 transformation_matrix = maths::create_transformation_matrix( 37 | entity.get_position(), 38 | entity.get_rot_x(), 39 | entity.get_rot_y(), 40 | entity.get_rot_z(), 41 | entity.get_scale()); 42 | shader.load_transformation_matrix(transformation_matrix); 43 | shader.load_offset(entity.get_texture_x_offset(), 44 | entity.get_texture_y_offset()); 45 | } 46 | 47 | void entity_renderer::unbind_textured_model() const 48 | { 49 | master_renderer::enable_culling(); 50 | glDisableVertexAttribArray(0); 51 | glDisableVertexAttribArray(1); 52 | glDisableVertexAttribArray(2); 53 | glBindVertexArray(0); 54 | } 55 | 56 | entity_renderer::entity_renderer(const static_shader& shader, 57 | const glm::mat4& projection_matrix) 58 | : projection_matrix{projection_matrix}, 59 | shader{shader} 60 | { 61 | shader.start(); 62 | shader.load_projection_matrix(projection_matrix); 63 | shader.stop(); 64 | } 65 | 66 | void entity_renderer::render(const entity_map &entities) const 67 | { 68 | for (const auto& entry : entities) { 69 | prepare_textured_model(entry.first); 70 | for (const auto& entity : entry.second) { 71 | prepare_instance(*entity); 72 | glDrawElements(GL_TRIANGLES, entry.first.raw.vertex_count, GL_UNSIGNED_INT, 0); 73 | } 74 | unbind_textured_model(); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/entity_renderer.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_RENDERER_HPP 3 | #define JAC_RENDERER_HPP 4 | 5 | #include "entity.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace jac { 12 | 13 | class static_shader; 14 | struct textured_model; 15 | 16 | class entity_renderer { 17 | public: 18 | using entity_map = std::unordered_map>; 19 | 20 | explicit entity_renderer(const static_shader& shader, 21 | const glm::mat4& projection_matrix); 22 | 23 | void render(const entity_map& entities) const; 24 | 25 | private: 26 | void prepare_textured_model(const jac::textured_model& model) const; 27 | void prepare_instance(const entity& entity) const; 28 | void unbind_textured_model() const; 29 | 30 | glm::mat4 projection_matrix; 31 | const static_shader& shader; 32 | }; 33 | 34 | 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/gl_handles.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_GL_HANDLES_HPP 3 | #define JAC_GL_HANDLES_HPP 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace jac { 10 | namespace gl { 11 | 12 | namespace detail { 13 | 14 | template 15 | class handle { 16 | public: 17 | handle() = default; 18 | handle(GLuint id) : id(id) {} 19 | 20 | handle(handle&& other) 21 | : id(other.id) 22 | { 23 | other.id = 0; 24 | } 25 | 26 | handle& operator=(handle&& other) 27 | { 28 | std::swap(id, other.id); 29 | return *this; 30 | } 31 | 32 | ~handle() 33 | { 34 | if (id) { 35 | Deleter{}(id); 36 | } 37 | } 38 | 39 | GLuint get() const { return id; } 40 | 41 | private: 42 | GLuint id = 0; 43 | }; 44 | 45 | template 46 | class multi_handle { 47 | public: 48 | multi_handle() = default; 49 | 50 | multi_handle(multi_handle&& other) 51 | : ids(std::move(other.ids)) 52 | { 53 | std::fill(std::begin(other.ids), std::end(other.ids), 0); 54 | } 55 | 56 | multi_handle& operator=(multi_handle&& other) 57 | { 58 | std::swap(ids, other.ids); 59 | return *this; 60 | } 61 | 62 | ~multi_handle() 63 | { 64 | Deleter()(N, ids.data()); 65 | } 66 | 67 | GLuint* operator&() 68 | { 69 | return ids.data(); 70 | } 71 | 72 | GLuint get(std::size_t n = 0) const { 73 | return ids[n]; 74 | } 75 | 76 | private: 77 | std::array ids = {}; 78 | }; 79 | 80 | struct gl_buffer_deleter { 81 | void operator()(GLsizei count, GLuint* ptr) const { 82 | glDeleteBuffers(count, ptr); 83 | } 84 | }; 85 | 86 | struct gl_framebuffer_deleter { 87 | void operator()(GLsizei count, GLuint* ptr) const { 88 | glDeleteFramebuffers(count, ptr); 89 | } 90 | }; 91 | 92 | struct gl_program_deleter { 93 | void operator()(GLuint handle) const { 94 | glDeleteProgram(handle); 95 | } 96 | }; 97 | 98 | struct gl_renderbuffer_deleter { 99 | void operator() (GLsizei count, GLuint* ptr) const { 100 | glDeleteRenderbuffers(count, ptr); 101 | } 102 | }; 103 | 104 | struct gl_shader_deleter { 105 | void operator()(GLuint handle) const { 106 | glDeleteShader(handle); 107 | } 108 | }; 109 | 110 | struct gl_texture_deleter { 111 | void operator()(GLsizei count, GLuint* ptr) const { 112 | glDeleteTextures(count, ptr); 113 | } 114 | }; 115 | 116 | struct gl_vertex_array_deleter { 117 | void operator()(GLsizei count, GLuint* ptr) const { 118 | glDeleteVertexArrays(count, ptr); 119 | } 120 | }; 121 | 122 | } // end namespace detail 123 | 124 | using buffer_handle = detail::multi_handle; 125 | using framebuffer_handle = detail::multi_handle; 126 | using program_handle = detail::handle; 127 | using renderbuffer_handle = detail::multi_handle; 128 | using shader_handle = detail::handle; 129 | using texture_handle = detail::multi_handle; 130 | using vertex_array_handle = detail::multi_handle; 131 | 132 | } // end namespace gl 133 | } // end namespace jac 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/gui_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "gui_renderer.hpp" 3 | 4 | #include "gui_texture.hpp" 5 | #include "loader.hpp" 6 | #include "maths.hpp" 7 | 8 | #include 9 | 10 | namespace jac { 11 | 12 | namespace { 13 | 14 | static const std::vector positions{ 15 | -1, 1, -1, -1, 1, 1, 1, -1 16 | }; 17 | 18 | } 19 | 20 | gui_renderer::gui_renderer(loader& loader) 21 | : quad{loader.load_to_vao(positions, 2)} 22 | {} 23 | 24 | void gui_renderer::render(const std::vector& guis) const 25 | { 26 | shader.start(); 27 | glBindVertexArray(quad.vao_id); 28 | glEnableVertexAttribArray(0); 29 | glEnable(GL_BLEND); 30 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 31 | glDisable(GL_DEPTH_TEST); 32 | for (const auto& gui : guis) { 33 | glActiveTexture(GL_TEXTURE0); 34 | glBindTexture(GL_TEXTURE_2D, gui.texture_id); 35 | auto matrix = maths::create_transformation_matrix(gui.position, 36 | gui.scale); 37 | shader.load_transformation(matrix); 38 | glDrawArrays(GL_TRIANGLE_STRIP, 0, quad.vertex_count); 39 | } 40 | glEnable(GL_DEPTH_TEST); 41 | glDisable(GL_BLEND); 42 | glDisableVertexAttribArray(0); 43 | glBindVertexArray(0); 44 | shader.stop(); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/gui_renderer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_GUI_RENDERER_HPP 2 | #define JAC_GUI_RENDERER_HPP 3 | 4 | #include "raw_model.hpp" 5 | #include "gui_shader.hpp" 6 | 7 | #include 8 | 9 | namespace jac { 10 | 11 | class loader; 12 | struct gui_texture; 13 | 14 | class gui_renderer { 15 | public: 16 | gui_renderer(loader& loader); 17 | 18 | void render(const std::vector& guis) const; 19 | 20 | private: 21 | const raw_model quad; 22 | gui_shader shader{}; 23 | }; 24 | 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/gui_shader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "gui_shader.hpp" 3 | 4 | constexpr const char vertex_file[] = "shaders/gui_vertex_shader.vert"; 5 | constexpr const char fragment_file[] = "shaders/gui_fragment_shader.frag"; 6 | 7 | namespace jac { 8 | 9 | gui_shader::gui_shader() 10 | : shader_program(vertex_file, fragment_file) 11 | { 12 | link(); 13 | } 14 | 15 | void gui_shader::load_transformation(const glm::mat4& matrix) const 16 | { 17 | load_matrix(location_transformation_matrix, matrix); 18 | } 19 | 20 | void gui_shader::bind_attributes() 21 | { 22 | bind_attribute(0, "position"); 23 | } 24 | 25 | void gui_shader::get_all_uniform_locations() 26 | { 27 | location_transformation_matrix = get_uniform_location("transformationMatrix"); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/gui_shader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_GUI_SHADER_HPP 2 | #define JAC_GUI_SHADER_HPP 3 | 4 | #include "shader_program.hpp" 5 | 6 | namespace jac { 7 | 8 | class gui_shader final : public shader_program 9 | { 10 | public: 11 | gui_shader(); 12 | 13 | void load_transformation(const glm::mat4& matrix) const; 14 | 15 | private: 16 | virtual void bind_attributes() override; 17 | virtual void get_all_uniform_locations() override; 18 | 19 | int location_transformation_matrix = 0; 20 | }; 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/gui_texture.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "gui_texture.hpp" -------------------------------------------------------------------------------- /src/gui_texture.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_GUI_TEXTURE_HPP 2 | #define JAC_GUI_TEXTURE_HPP 3 | 4 | #include 5 | 6 | namespace jac { 7 | 8 | struct gui_texture { 9 | unsigned texture_id = 0; 10 | glm::vec2 position{}; 11 | glm::vec2 scale{}; 12 | }; 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/light.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "light.hpp" 3 | -------------------------------------------------------------------------------- /src/light.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_LIGHT_HPP 2 | #define JAC_LIGHT_HPP 3 | 4 | #include 5 | 6 | namespace jac { 7 | 8 | struct light { 9 | glm::vec3 position{}; 10 | glm::vec3 colour{}; 11 | glm::vec3 attenuation{1, 0, 0}; 12 | }; 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/loader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "loader.hpp" 3 | 4 | #include "gl_handles.hpp" 5 | #include "raw_model.hpp" 6 | #include "sdl_handles.hpp" 7 | #include "stb_image.hpp" 8 | 9 | #include "SDL.h" 10 | 11 | namespace jac { 12 | 13 | GLuint loader::create_vao() 14 | { 15 | gl::vertex_array_handle vao; 16 | glGenVertexArrays(1, &vao); 17 | auto vao_id = vao.get(); 18 | glBindVertexArray(vao_id); 19 | vaos.push_back(std::move(vao)); 20 | return vao_id; 21 | } 22 | 23 | GLuint loader::create_vbo() 24 | { 25 | gl::buffer_handle vbo; 26 | glGenBuffers(1, &vbo); 27 | auto vbo_id = vbo.get(); 28 | vbos.push_back(std::move(vbo)); 29 | return vbo_id; 30 | } 31 | 32 | void loader::store_data_in_attribute_list(GLuint attrib_num, 33 | int coord_size, 34 | const std::vector& data) 35 | { 36 | GLuint vbo_id = create_vbo(); 37 | glBindBuffer(GL_ARRAY_BUFFER, vbo_id); 38 | 39 | glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), 40 | data.data(), GL_STATIC_DRAW); 41 | 42 | glVertexAttribPointer(attrib_num, coord_size, GL_FLOAT, GL_FALSE, 0, nullptr); 43 | 44 | glBindBuffer(GL_ARRAY_BUFFER, 0); 45 | } 46 | 47 | void loader::unbind_vao() 48 | { 49 | glBindVertexArray(0); 50 | } 51 | 52 | void loader::bind_indices_buffer(const std::vector& indices) 53 | { 54 | GLuint vbo = create_vbo(); 55 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo); 56 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(int), 57 | indices.data(), GL_STATIC_DRAW); 58 | } 59 | 60 | raw_model 61 | loader::load_to_vao(const std::vector& positions, 62 | const std::vector& texture_coords, 63 | const std::vector& normals, 64 | const std::vector& indices) 65 | { 66 | auto vao_id = create_vao(); 67 | bind_indices_buffer(indices); 68 | store_data_in_attribute_list(0, 3, positions); 69 | store_data_in_attribute_list(1, 2, texture_coords); 70 | store_data_in_attribute_list(2, 3, normals); 71 | unbind_vao(); 72 | raw_model model{vao_id, int(indices.size())}; 73 | return model; 74 | } 75 | 76 | GLuint 77 | loader::load_texture(const std::string& filename) 78 | { 79 | stb::image image("res/" + filename + ".png"); 80 | SDL_assert(image); 81 | 82 | gl::texture_handle texture; 83 | glGenTextures(1, &texture); 84 | GLuint texture_id = texture.get(); 85 | textures.push_back(std::move(texture)); 86 | 87 | GLenum mode = (image.num_components() == 4 ? GL_RGBA : GL_RGB); 88 | glBindTexture(GL_TEXTURE_2D, texture_id); 89 | glTexImage2D(GL_TEXTURE_2D, 0, mode, image.width(), image.height(), 0, mode, 90 | GL_UNSIGNED_BYTE, image.data()); 91 | glGenerateMipmap(GL_TEXTURE_2D); 92 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 93 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 94 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.4f); 95 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 96 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 97 | 98 | return texture_id; 99 | } 100 | 101 | raw_model loader::load_to_vao(const std::vector& positions, 102 | int dimensions) 103 | { 104 | GLuint vao_id = create_vao(); 105 | store_data_in_attribute_list(0, dimensions, positions); 106 | unbind_vao(); 107 | return raw_model{vao_id, int(positions.size()/dimensions)}; 108 | } 109 | 110 | GLuint loader::load_cube_map(const std::vector& texture_files) 111 | { 112 | gl::texture_handle texture; 113 | glGenTextures(1, &texture); 114 | auto tex_id = texture.get(); 115 | textures.push_back(std::move(texture)); 116 | glActiveTexture(GL_TEXTURE0); 117 | glBindTexture(GL_TEXTURE_CUBE_MAP, tex_id); 118 | 119 | for (int i = 0; i < texture_files.size(); i++) { 120 | auto image = stb::image("res/" + texture_files[i] + ".png", 4); 121 | SDL_assert(image); 122 | 123 | glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 124 | image.width(), image.height(), 0, 125 | GL_RGBA, GL_UNSIGNED_BYTE, image.data()); 126 | } 127 | 128 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 129 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 130 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 131 | glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 132 | return tex_id; 133 | } 134 | 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/loader.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef KTX_VIEWER_LOADER_HPP 3 | #define KTX_VIEWER_LOADER_HPP 4 | 5 | #include "gl_handles.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace jac { 12 | 13 | struct raw_model; 14 | 15 | class loader { 16 | public: 17 | raw_model load_to_vao(const std::vector& data, 18 | const std::vector& texture_coords, 19 | const std::vector& normals, 20 | const std::vector& indices); 21 | 22 | raw_model load_to_vao(const std::vector& positions, 23 | int dimensions); 24 | 25 | GLuint load_texture(const std::string& filename); 26 | 27 | GLuint load_cube_map(const std::vector& texture_files); 28 | 29 | private: 30 | GLuint create_vao(); 31 | GLuint create_vbo(); 32 | void store_data_in_attribute_list(GLuint attrib_num, 33 | int coord_size, 34 | const std::vector& data); 35 | void unbind_vao(); 36 | void bind_indices_buffer(const std::vector& indices); 37 | 38 | 39 | std::vector vaos; 40 | std::vector vbos; 41 | std::vector textures; 42 | }; 43 | 44 | } // end namespace jac 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/main_game_loop.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "camera.hpp" 3 | #include "display_manager.hpp" 4 | #include "entity.hpp" 5 | #include "gui_texture.hpp" 6 | #include "gui_renderer.hpp" 7 | #include "light.hpp" 8 | #include "loader.hpp" 9 | #include "master_renderer.hpp" 10 | #include "obj_loader.hpp" 11 | #include "player.hpp" 12 | #include "terrain.hpp" 13 | 14 | #include "SDL.h" 15 | #include "mouse_picker.hpp" 16 | #include "water_shader.hpp" 17 | #include "water_renderer.hpp" 18 | #include "water_tile.hpp" 19 | #include "water_frame_buffers.hpp" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | int main() 28 | { 29 | SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER); 30 | 31 | auto display = jac::create_display(); 32 | auto loader = jac::loader{}; 33 | 34 | // Terrain texure stuff 35 | auto background_texture = jac::terrain_texture{loader.load_texture("grassy")}; 36 | auto r_texture = jac::terrain_texture{loader.load_texture("dirt")}; 37 | auto g_texture = jac::terrain_texture{loader.load_texture("pinkFlowers")}; 38 | auto b_texture = jac::terrain_texture{loader.load_texture("path")}; 39 | auto texture_pack = jac::terrain_texture_pack{background_texture, r_texture, 40 | g_texture, b_texture}; 41 | auto blend_map = jac::terrain_texture{loader.load_texture("blendMap")}; 42 | 43 | 44 | auto tree = jac::textured_model{jac::load_obj_model("tree", loader), 45 | jac::model_texture{loader.load_texture("tree")}}; 46 | 47 | auto grass = jac::textured_model{jac::load_obj_model("grassModel", loader), 48 | jac::model_texture{loader.load_texture("grassTexture")}}; 49 | grass.texture.has_transparency = true; 50 | grass.texture.use_fake_lighting = true; 51 | 52 | auto flower = jac::textured_model{grass.raw, 53 | jac::model_texture{loader.load_texture("flower")}}; 54 | flower.texture.has_transparency = true; 55 | flower.texture.use_fake_lighting = true; 56 | 57 | auto fern = jac::textured_model{jac::load_obj_model("fern", loader), 58 | jac::model_texture{loader.load_texture("fern")}}; 59 | fern.texture.has_transparency = true; 60 | fern.texture.number_of_rows = 2; 61 | 62 | auto bobble = jac::textured_model{jac::load_obj_model("lowPolyTree", loader), 63 | jac::model_texture{loader.load_texture("lowPolyTree")}}; 64 | 65 | auto lamp = jac::textured_model{jac::load_obj_model("lamp", loader), 66 | jac::model_texture{loader.load_texture("lamp")}}; 67 | lamp.texture.use_fake_lighting = true; 68 | 69 | auto lights = std::vector{ 70 | jac::light{{0, 1000, 7000}, {1.0f, 1.0f, 1.0f}}, 71 | jac::light{{185, 10, -293}, {2, 0, 0}, {1, 0.01f, 0.002f}}, 72 | jac::light{{370, 17, -300}, {0, 2, 2}, {1, 0.01f, 0.002f}}, 73 | jac::light{{293, 7, -305}, {2, 2, 0}, {1, 0.01f, 0.002f}} 74 | }; 75 | 76 | auto terrain = jac::terrain{0, -1, loader, texture_pack, blend_map, "heightmap"}; 77 | 78 | std::vector entities; 79 | std::random_device rd{}; 80 | std::mt19937 gen{rd()}; 81 | std::uniform_real_distribution dist{0, 1.0f}; 82 | std::uniform_int_distribution rand_int{0, 3}; 83 | 84 | auto rand_vec = [&] { 85 | float x = dist(gen) * 800; 86 | float z = dist(gen) * -800; 87 | return glm::vec3{x, terrain.get_height_of_terrain(x, z), z}; 88 | }; 89 | 90 | for (int i = 0; i < 400; i++) { 91 | if (i % 7 == 0) { 92 | entities.push_back(jac::entity{grass, 93 | rand_vec(), 94 | 0, 0, 0, 1.8f}); 95 | entities.push_back(jac::entity{flower, 96 | rand_vec(), 97 | 0, 0, 0, 2.3f}); 98 | } 99 | if (i % 3 == 0) { 100 | entities.push_back(jac::entity{fern, rand_int(gen), 101 | rand_vec(), 102 | 0, dist(gen) * 360, 0, 0.9f}); 103 | entities.push_back(jac::entity{bobble, 104 | rand_vec(), 105 | 0, dist(gen) * 360, 0, dist(gen) * 0.1f + 0.6f}); 106 | entities.push_back(jac::entity{tree, 107 | rand_vec(), 108 | 0, dist(gen) * 360, 0, dist(gen) * 1.0f + 4.0f}); 109 | } 110 | } 111 | 112 | entities.push_back(jac::entity{lamp, {185, -4.7f, -293}, 0, 0, 0, 1}); 113 | entities.push_back(jac::entity{lamp, {370, 4.2f, -300}, 0, 0, 0, 1}); 114 | entities.push_back(jac::entity{lamp, {293, -6.8f, -305}, 0, 0, 0, 1}); 115 | 116 | //auto dragon = jac::textured_model{jac::load_obj_model("dragon", loader), 117 | // jac::model_texture{loader.load_texture("grass")}}; 118 | //entities.push_back(jac::entity{dragon, {100, 0, -50}, 0, 0, 0, 3.0}); 119 | 120 | auto person = jac::textured_model{jac::load_obj_model("person", loader), 121 | jac::model_texture{loader.load_texture("playerTexture")}}; 122 | 123 | auto player = jac::player(person, glm::vec3{400, 0, -400}, 0, 0, 0, 1.0f); 124 | auto camera = jac::camera{player}; 125 | 126 | auto renderer = jac::master_renderer{loader}; 127 | 128 | auto guis = std::vector{}; 129 | guis.push_back(jac::gui_texture{loader.load_texture("health"), 130 | glm::vec2(-0.75, 0.90), 131 | glm::vec2(0.25, 0.25)}); 132 | 133 | auto gui_renderer = jac::gui_renderer{loader}; 134 | 135 | auto picker = jac::mouse_picker{camera, renderer.get_projection_matrix()}; 136 | 137 | 138 | /* Water renderer setup */ 139 | auto fbos = jac::water_frame_buffers{}; 140 | auto water_renderer = jac::water_renderer{loader, 141 | jac::water_shader{}, 142 | renderer.get_projection_matrix(), 143 | fbos}; 144 | auto waters = std::vector{}; 145 | waters.push_back(jac::water_tile{247, -276, -7}); 146 | 147 | bool quit_requested = false; 148 | while (!quit_requested) { 149 | SDL_Event e; 150 | while (SDL_PollEvent(&e)) { 151 | switch (e.type) { 152 | case SDL_QUIT: 153 | quit_requested = true; 154 | break; 155 | case SDL_MOUSEMOTION: 156 | camera.mouse_move(e.motion.xrel, e.motion.yrel); 157 | break; 158 | case SDL_MOUSEWHEEL: 159 | camera.mouse_wheel(e.wheel.y); 160 | break; 161 | } 162 | } 163 | 164 | player.move(terrain); 165 | camera.move(); 166 | picker.update(); 167 | 168 | glEnable(GL_CLIP_DISTANCE0); 169 | 170 | // Render water reflection 171 | { 172 | fbos.bind_reflection_frame_buffer(); 173 | auto cam2 = camera; 174 | float distance = 2 * (cam2.get_position().y - waters[0].height); 175 | auto pos = cam2.get_position() - glm::vec3{0, distance, 0}; 176 | cam2.set_position(pos); 177 | cam2.invert_pitch(); 178 | renderer.render_scene(entities, player, terrain, lights, cam2, 179 | glm::vec4{0, 1, 0, -waters[0].height}); 180 | fbos.unbind_current_frame_buffer(); 181 | } 182 | 183 | 184 | fbos.bind_refraction_frame_buffer(); 185 | renderer.render_scene(entities, player, terrain, lights, camera, 186 | {0, -1, 0, waters[0].height + 0.5f}); 187 | fbos.unbind_current_frame_buffer(); 188 | 189 | // TODO: Something interesting with the picked ray 190 | 191 | renderer.render_scene(entities, player, terrain, lights, camera, {0, -1, 0, 2000}); 192 | water_renderer.render(waters, camera, lights.front()); 193 | gui_renderer.render(guis); 194 | 195 | jac::update_display(display); 196 | } 197 | 198 | SDL_Quit(); 199 | } 200 | -------------------------------------------------------------------------------- /src/master_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "master_renderer.hpp" 3 | 4 | #include "camera.hpp" 5 | #include "entity.hpp" 6 | #include "light.hpp" 7 | #include "loader.hpp" 8 | #include "player.hpp" 9 | #include "entity_renderer.hpp" 10 | #include "static_shader.hpp" 11 | #include "terrain_renderer.hpp" 12 | #include "terrain_shader.hpp" 13 | #include "textured_model.hpp" 14 | 15 | #include "SDL.h" 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | namespace { 26 | 27 | constexpr float fov = 70; // degrees 28 | constexpr float near_plane = 0.1f; 29 | constexpr float far_plane = 1000.0f; 30 | constexpr float sky_red = 0.35f;//0.53f; 31 | constexpr float sky_green = 0.46f;//0.81f; 32 | constexpr float sky_blue = 0.5;//0.92f; 33 | 34 | } 35 | 36 | 37 | namespace jac { 38 | 39 | glm::mat4 master_renderer::create_projection_matrix() 40 | { 41 | int w, h; 42 | SDL_GL_GetDrawableSize(SDL_GL_GetCurrentWindow(), &w, &h); 43 | // This is certainly easier than the Java version... 44 | return glm::perspectiveFov(glm::radians(fov), float(w), float(h), 45 | near_plane, far_plane); 46 | } 47 | 48 | 49 | master_renderer::master_renderer(loader& loader) 50 | : skybox_renderer{loader, projection_matrix} 51 | { 52 | enable_culling(); 53 | } 54 | 55 | void master_renderer::prepare() const 56 | { 57 | glEnable(GL_DEPTH_TEST); 58 | glClearColor(sky_red, sky_green, sky_blue, 1.0f); 59 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 60 | } 61 | 62 | void master_renderer::render(const std::vector& lights, 63 | const jac::camera& cam, 64 | const glm::vec4& clip_plane) 65 | { 66 | prepare(); 67 | shader.start(); 68 | shader.load_clip_plane(clip_plane); 69 | shader.load_sky_colour(sky_red, sky_green, sky_blue); 70 | shader.load_lights(lights); 71 | shader.load_view_matrix(cam); 72 | entity_renderer.render(entities); 73 | shader.stop(); 74 | 75 | terrain_shader.start(); 76 | terrain_shader.load_clip_plane(clip_plane); 77 | terrain_shader.load_sky_colour(sky_red, sky_green, sky_blue); 78 | terrain_shader.load_lights(lights); 79 | terrain_shader.load_view_matrix(cam); 80 | terrain_renderer.render(terrains); 81 | terrain_shader.stop(); 82 | 83 | skybox_renderer.render(cam, sky_red, sky_green, sky_blue); 84 | 85 | terrains.clear(); 86 | entities.clear(); 87 | } 88 | 89 | void master_renderer::process_terrain(const terrain& terrain) 90 | { 91 | terrains.push_back(&terrain); 92 | } 93 | 94 | void master_renderer::process_entity(const entity& entity) 95 | { 96 | const auto& entity_model = entity.get_model(); 97 | 98 | auto& batch = entities[entity_model]; 99 | batch.push_back(&entity); 100 | } 101 | 102 | void master_renderer::enable_culling() 103 | { 104 | glEnable(GL_CULL_FACE); 105 | glCullFace(GL_BACK); 106 | } 107 | 108 | void master_renderer::disable_culling() 109 | { 110 | glDisable(GL_CULL_FACE); 111 | } 112 | 113 | void master_renderer::render_scene(const std::vector& entities, 114 | const jac::player& player, 115 | const jac::terrain& terrain, 116 | const std::vector& lights, 117 | const jac::camera& camera, 118 | const glm::vec4& clip_plane) 119 | { 120 | process_terrain(terrain); 121 | process_entity(player); 122 | 123 | for (const auto& e : entities) { 124 | process_entity(e); 125 | } 126 | 127 | render(lights, camera, clip_plane); 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/master_renderer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_MASTER_RENDERER_HPP 2 | #define JAC_MASTER_RENDERER_HPP 3 | 4 | #include "entity_renderer.hpp" 5 | #include "skybox_renderer.hpp" 6 | #include "static_shader.hpp" 7 | #include "terrain_renderer.hpp" 8 | #include "terrain_shader.hpp" 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace jac { 16 | 17 | class camera; 18 | class entity; 19 | struct light; 20 | class loader; 21 | class player; 22 | class terrain; 23 | struct textured_model; 24 | 25 | class master_renderer 26 | { 27 | public: 28 | master_renderer(loader& loader); 29 | 30 | void prepare() const; 31 | 32 | void render_scene(const std::vector& entities, 33 | const jac::player& player, 34 | const jac::terrain& terrain, 35 | const std::vector& lights, 36 | const jac::camera& camera, 37 | const glm::vec4& clip_plane); 38 | 39 | void render(const std::vector& sun, 40 | const camera& cam, 41 | const glm::vec4& clip_plane); 42 | 43 | void process_entity(const entity& entity); 44 | void process_terrain(const terrain& terrain); 45 | 46 | const glm::mat4& get_projection_matrix() const { return projection_matrix; } 47 | 48 | static void enable_culling(); 49 | static void disable_culling(); 50 | 51 | private: 52 | using terrain_list = std::vector; 53 | using entity_map = std::unordered_map>; 54 | 55 | static glm::mat4 create_projection_matrix(); 56 | 57 | static_shader shader{}; 58 | glm::mat4 projection_matrix{create_projection_matrix()}; 59 | jac::entity_renderer entity_renderer{shader, projection_matrix}; 60 | jac::skybox_renderer skybox_renderer; 61 | jac::terrain_shader terrain_shader{}; 62 | jac::terrain_renderer terrain_renderer{terrain_shader, projection_matrix}; 63 | 64 | entity_map entities; 65 | terrain_list terrains; 66 | }; 67 | 68 | 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/maths.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "maths.hpp" 3 | 4 | #include "camera.hpp" 5 | 6 | #include 7 | 8 | namespace jac { 9 | namespace maths { 10 | 11 | glm::mat4 create_transformation_matrix(const glm::vec3& translation, 12 | float rx, float ry, float rz, 13 | float scale) 14 | { 15 | glm::mat4 matrix{}; 16 | 17 | matrix = glm::translate(matrix, translation); 18 | matrix = glm::rotate(matrix, glm::radians(rx), glm::vec3{1, 0, 0}); 19 | matrix = glm::rotate(matrix, glm::radians(ry), glm::vec3{0, 1, 0}); 20 | matrix = glm::rotate(matrix, glm::radians(rz), glm::vec3{0, 0, 1}); 21 | matrix = glm::scale(matrix, glm::vec3{scale, scale, scale}); 22 | 23 | return matrix; 24 | } 25 | 26 | glm::mat4 create_view_matrix(const camera& cam) 27 | { 28 | glm::mat4 view_matrix{}; 29 | 30 | view_matrix = glm::rotate(view_matrix, glm::radians(cam.get_pitch()), {1, 0, 0}); 31 | view_matrix = glm::rotate(view_matrix, glm::radians(cam.get_yaw()), {0, 1, 0}); 32 | view_matrix = glm::translate(view_matrix, -cam.get_position()); 33 | 34 | return view_matrix; 35 | } 36 | 37 | float barrycentric(const glm::vec3& p1, const glm::vec3& p2, 38 | const glm::vec3& p3, const glm::vec2& pos) 39 | { 40 | float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z); 41 | float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det; 42 | float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det; 43 | float l3 = 1.0f - l1 - l2; 44 | return l1 * p1.y + l2 * p2.y + l3 * p3.y; 45 | } 46 | 47 | glm::mat4 create_transformation_matrix(const glm::vec2& translation, 48 | const glm::vec2& scale) 49 | { 50 | glm::mat4 matrix{}; 51 | matrix = glm::translate(matrix, glm::vec3{translation, 0.0f}); 52 | matrix = glm::scale(matrix, glm::vec3{scale, 1.0f}); 53 | return matrix; 54 | } 55 | 56 | 57 | } 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/maths.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_MATHS_HPP 2 | #define JAC_MATHS_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace jac { 8 | 9 | class camera; 10 | 11 | namespace maths { 12 | 13 | float barrycentric(const glm::vec3& p1, 14 | const glm::vec3& p2, 15 | const glm::vec3& p3, 16 | const glm::vec2& pos); 17 | 18 | glm::mat4 create_transformation_matrix(const glm::vec3& translation, 19 | float rx, float ry, float rz, 20 | float scale); 21 | 22 | glm::mat4 create_transformation_matrix(const glm::vec2& translation, 23 | const glm::vec2& scale); 24 | 25 | glm::mat4 create_view_matrix(const camera& cam); 26 | 27 | } 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/model_texture.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "model_texture.hpp" 3 | 4 | -------------------------------------------------------------------------------- /src/model_texture.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_MODEL_TEXTURE_HPP 2 | #define JAC_MODEL_TEXTURE_HPP 3 | 4 | #include 5 | #include 6 | 7 | namespace jac { 8 | 9 | struct model_texture { 10 | unsigned texture_id = 0; 11 | float shine_damper = 1; 12 | float reflectivity = 0; 13 | bool has_transparency = false; 14 | bool use_fake_lighting = false; 15 | int number_of_rows = 1; 16 | }; 17 | 18 | inline bool operator==(const model_texture& lhs, const model_texture& rhs) 19 | { 20 | return std::tie(lhs.texture_id, lhs.shine_damper, lhs.reflectivity) == 21 | std::tie(rhs.texture_id, rhs.shine_damper, rhs.reflectivity); 22 | } 23 | 24 | } 25 | 26 | namespace std { 27 | 28 | template <> 29 | struct hash { 30 | using argument_type = jac::model_texture; 31 | using result_type = size_t; 32 | 33 | size_t operator()(const jac::model_texture& texture) noexcept { 34 | return hash{}(texture.texture_id) ^ 35 | hash{}(texture.shine_damper) ^ 36 | hash{}(texture.reflectivity); 37 | } 38 | }; 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/mouse_picker.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "mouse_picker.hpp" 3 | #include "maths.hpp" 4 | 5 | #include "SDL.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace { 11 | 12 | glm::vec2 get_normalised_device_coords(float mouse_x, float mouse_y) 13 | { 14 | int w, h; 15 | SDL_Window* win = SDL_GL_GetCurrentWindow(); 16 | SDL_assert(win); 17 | SDL_GetWindowSize(win, &w, &h); 18 | 19 | float x = (2.0f * mouse_x)/(float)w - 1.0f; 20 | float y = (2.0f * mouse_y)/(float)h - 1.0f; 21 | 22 | return {x, -y}; 23 | } 24 | 25 | glm::vec4 to_eye_coords(const glm::vec4& clip_coords, const glm::mat4& proj_mat) 26 | { 27 | glm::vec4 eye_coords = glm::inverse(proj_mat) * clip_coords; 28 | return { eye_coords.x, eye_coords.y, -1.0, 0.0}; 29 | } 30 | 31 | glm::vec3 to_world_coords(const glm::vec4& eye_coords, const glm::mat4& view_mat) 32 | { 33 | auto mouse_ray = glm::vec3{glm::inverse(view_mat) * eye_coords}; 34 | return normalize(mouse_ray); 35 | } 36 | 37 | } 38 | 39 | 40 | namespace jac { 41 | 42 | mouse_picker::mouse_picker(const camera& cam, const glm::mat4& projection) 43 | : cam{cam}, 44 | projection_matrix{projection}, 45 | view_matrix{maths::create_view_matrix(cam)} 46 | {} 47 | 48 | void mouse_picker::update() 49 | { 50 | view_matrix = maths::create_view_matrix(cam); 51 | current_ray = calculate_mouse_ray(); 52 | } 53 | 54 | glm::vec3 mouse_picker::calculate_mouse_ray() 55 | { 56 | float mouse_x = 0; 57 | float mouse_y = 0; 58 | 59 | { 60 | int imouse_x, imouse_y; 61 | SDL_GetMouseState(&imouse_x, &imouse_y); 62 | mouse_x = imouse_x; mouse_y = imouse_y; 63 | } 64 | 65 | auto normalized_coords = get_normalised_device_coords(mouse_x, mouse_y); 66 | auto clip_coords = glm::vec4(normalized_coords, -1.0f, 1.0f); 67 | auto eye_coords = to_eye_coords(clip_coords, projection_matrix); 68 | auto world_ray = to_world_coords(eye_coords, view_matrix); 69 | 70 | return world_ray; 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/mouse_picker.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_MOUSE_PICKER_HPP 3 | #define JAC_MOUSE_PICKER_HPP 4 | 5 | #include "camera.hpp" 6 | 7 | #include 8 | 9 | namespace jac { 10 | 11 | class mouse_picker { 12 | public: 13 | mouse_picker(const camera& cam, const glm::mat4& projection); 14 | 15 | const glm::vec3& get_current_ray() const { return current_ray; } 16 | 17 | void update(); 18 | 19 | private: 20 | glm::vec3 calculate_mouse_ray(); 21 | 22 | const camera& cam; 23 | glm::mat4 projection_matrix; 24 | glm::mat4 view_matrix; 25 | glm::vec3 current_ray; 26 | }; 27 | 28 | } 29 | 30 | #endif //JAC_MOUSE_PICKER_HPP 31 | -------------------------------------------------------------------------------- /src/obj_loader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "obj_loader.hpp" 3 | 4 | #include "raw_model.hpp" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace { 14 | 15 | // http://tcbrindle.github.io/posts/a-quicker-study-on-tokenising/ 16 | std::vector 17 | split(const std::string& str, const std::string& delims = " ", 18 | bool skip_empty = true) 19 | { 20 | std::vector output; 21 | auto first = std::cbegin(str); 22 | 23 | while (first != std::cend(str)) { 24 | const auto second = std::find_first_of(first, std::cend(str), 25 | std::cbegin(delims), std::cend(delims)); 26 | if (first != second || !skip_empty) { 27 | output.emplace_back(first, second); 28 | } 29 | if (second == std::cend(str)) break; 30 | first = std::next(second); 31 | } 32 | 33 | return output; 34 | } 35 | 36 | bool 37 | starts_with(const std::string& str, const std::string& prefix) 38 | { 39 | auto p = std::mismatch(std::cbegin(prefix), std::cend(prefix), 40 | std::cbegin(str), std::cend(str)); 41 | 42 | return p.first == std::cend(prefix); 43 | } 44 | 45 | } 46 | 47 | namespace jac { 48 | 49 | raw_model load_obj_model(const std::string& filename, 50 | loader& loader) 51 | { 52 | std::ifstream file{"res/" + filename + ".obj"}; 53 | //file.exceptions(std::ios::failbit); 54 | 55 | std::vector vertices; 56 | std::vector textures; 57 | std::vector normals; 58 | std::vector indices; 59 | 60 | std::vector vertices_array; 61 | std::vector texture_array; 62 | std::vector normals_array; 63 | 64 | std::string line; 65 | 66 | while (true) { 67 | std::getline(file, line); 68 | if (line.empty()) { 69 | continue; 70 | } 71 | 72 | auto current_line = split(line); 73 | if (starts_with(line, "v ")) { 74 | vertices.emplace_back(std::stof(current_line.at(1)), 75 | std::stof(current_line.at(2)), 76 | std::stof(current_line.at(3))); 77 | } 78 | else if (starts_with(line, "vt ")) { 79 | textures.emplace_back(std::stof(current_line.at(1)), 80 | std::stof(current_line.at(2))); 81 | } 82 | else if (starts_with(line, "vn ")) { 83 | normals.emplace_back(std::stof(current_line.at(1)), 84 | std::stof(current_line.at(2)), 85 | std::stof(current_line.at(3))); 86 | } 87 | else if (starts_with(line, "f ")) { 88 | texture_array.resize(vertices.size() * 2); 89 | normals_array.resize(vertices.size() * 3); 90 | break; 91 | } 92 | } 93 | 94 | while (!line.empty()) { 95 | if (!starts_with(line, "f ")) { 96 | std::getline(file, line); 97 | continue; 98 | } 99 | 100 | auto current_line = split(line); 101 | auto vertex1 = split(current_line.at(1), "/"); 102 | auto vertex2 = split(current_line.at(2), "/"); 103 | auto vertex3 = split(current_line.at(3), "/"); 104 | 105 | auto process_vertex = [&] (const auto& vertex_data) { 106 | int current_vertex_pointer = std::stoi(vertex_data.at(0)) - 1; 107 | indices.push_back(current_vertex_pointer); 108 | 109 | glm::vec2 current_tex = textures.at(std::stoi(vertex_data.at(1)) - 1); 110 | texture_array.at(current_vertex_pointer * 2) = current_tex.x; 111 | texture_array.at(current_vertex_pointer * 2 + 1) = 1.0f - current_tex.y; 112 | 113 | glm::vec3 current_norm = normals.at(std::stoi(vertex_data.at(2)) - 1); 114 | normals_array.at(current_vertex_pointer * 3) = current_norm.x; 115 | normals_array.at(current_vertex_pointer * 3 + 1) = current_norm.y; 116 | normals_array.at(current_vertex_pointer * 3 + 2) = current_norm.z; 117 | }; 118 | 119 | process_vertex(vertex1); 120 | process_vertex(vertex2); 121 | process_vertex(vertex3); 122 | 123 | std::getline(file, line); 124 | } 125 | 126 | // Will this function never end... 127 | 128 | vertices_array.reserve(vertices.size() * 3); 129 | 130 | for (const auto& vertex : vertices) { 131 | vertices_array.push_back(vertex.x); 132 | vertices_array.push_back(vertex.y); 133 | vertices_array.push_back(vertex.z); 134 | } 135 | 136 | return loader.load_to_vao(vertices_array, texture_array, normals_array, indices); 137 | } 138 | 139 | 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/obj_loader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_OBJ_LOADER_HPP 2 | #define JAC_OBJ_LOADER_HPP 3 | 4 | #include "loader.hpp" 5 | 6 | #include 7 | 8 | namespace jac { 9 | 10 | raw_model load_obj_model(const std::string& filename, 11 | loader& loader); 12 | 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/player.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "player.hpp" 3 | 4 | #include "display_manager.hpp" 5 | #include "terrain.hpp" 6 | 7 | #include "SDL.h" 8 | 9 | #include 10 | 11 | constexpr float run_speed = 20; 12 | constexpr float turn_speed = 160; 13 | constexpr float gravity = -50; 14 | constexpr float jump_power = 30; 15 | 16 | constexpr float to_radians(float degrees) { 17 | return degrees * M_PI/180.0; 18 | } 19 | 20 | namespace jac { 21 | 22 | void player::move(const terrain& terrain) { 23 | check_inputs(); 24 | increase_rotation(0, current_turn_speed * get_frame_time_seconds().count(), 25 | 0); 26 | const auto distance = current_speed * get_frame_time_seconds().count(); 27 | const auto dx = distance * std::sin(to_radians(get_rot_y())); 28 | const auto dz = distance * std::cos(to_radians(get_rot_y())); 29 | increase_position(dx, 0, dz); 30 | 31 | upwards_speed += gravity * get_frame_time_seconds().count(); 32 | increase_position(0, upwards_speed * get_frame_time_seconds().count(), 0); 33 | float terrain_height = terrain.get_height_of_terrain(get_position().x, 34 | get_position().z); 35 | 36 | if (position.y < terrain_height) { 37 | upwards_speed = 0; 38 | is_in_air = false; 39 | position.y = terrain_height; 40 | } else if (position.y > terrain_height) { 41 | is_in_air = true; 42 | } 43 | 44 | current_speed = 0; 45 | current_turn_speed = 0; 46 | } 47 | 48 | void player::check_inputs() { 49 | auto state = SDL_GetKeyboardState(nullptr); 50 | 51 | if (state[SDL_SCANCODE_W]) { 52 | current_speed = run_speed; 53 | } else if (state[SDL_SCANCODE_S]) { 54 | current_speed = -run_speed; 55 | } else { 56 | //current_speed = 0; 57 | } 58 | 59 | if (state[SDL_SCANCODE_D]) { 60 | current_turn_speed = -turn_speed; 61 | } else if (state[SDL_SCANCODE_A]) { 62 | current_turn_speed = turn_speed; 63 | } else { 64 | //current_turn_speed = 0; 65 | } 66 | 67 | if (state[SDL_SCANCODE_SPACE]) { 68 | jump(); 69 | } 70 | } 71 | 72 | void player::jump() { 73 | if (!is_in_air) { 74 | upwards_speed += jump_power; 75 | } 76 | } 77 | 78 | void player::turn_left() 79 | { 80 | current_turn_speed = -turn_speed; 81 | } 82 | 83 | void player::turn_right() 84 | { 85 | current_turn_speed = turn_speed; 86 | } 87 | 88 | void player::move_forward() 89 | { 90 | current_speed = run_speed; 91 | } 92 | 93 | void player::move_back() 94 | { 95 | current_speed = -run_speed; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/player.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_PLAYER_HPP 3 | #define JAC_PLAYER_HPP 4 | 5 | #include "entity.hpp" 6 | 7 | namespace jac { 8 | 9 | class terrain; 10 | 11 | class player : public entity { 12 | public: 13 | using entity::entity; 14 | 15 | void move(const terrain& terrain); 16 | void jump(); 17 | void turn_left(); 18 | void turn_right(); 19 | void move_forward(); 20 | void move_back(); 21 | 22 | private: 23 | void check_inputs(); 24 | 25 | float current_speed = 0; 26 | float current_turn_speed = 0; 27 | float upwards_speed = 0; 28 | bool is_in_air = false; 29 | }; 30 | 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/raw_model.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "raw_model.hpp" 3 | 4 | -------------------------------------------------------------------------------- /src/raw_model.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_RAW_MODEL_HPP 3 | #define JAC_RAW_MODEL_HPP 4 | 5 | #include 6 | 7 | namespace jac { 8 | 9 | struct raw_model { 10 | unsigned vao_id; 11 | int vertex_count; 12 | }; 13 | 14 | inline bool operator==(const raw_model& lhs, const raw_model& rhs) 15 | { 16 | return lhs.vao_id == rhs.vao_id && lhs.vertex_count == rhs.vertex_count; 17 | } 18 | 19 | } // end namespace jac 20 | 21 | namespace std { 22 | 23 | template <> 24 | struct hash { 25 | using argument_type = jac::raw_model; 26 | using result_type = size_t; 27 | 28 | size_t operator()(const jac::raw_model& model) noexcept { 29 | return hash{}(model.vao_id) ^ 30 | hash{}(model.vertex_count); 31 | } 32 | }; 33 | 34 | } 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/sdl_handles.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_SDL_HANDLES_HPP 3 | #define JAC_SDL_HANDLES_HPP 4 | 5 | #include "stb_image.h" 6 | 7 | #include "SDL.h" 8 | 9 | #include 10 | 11 | namespace jac { 12 | 13 | namespace detail { 14 | 15 | template 16 | struct sdl_deleter { 17 | void operator()(T* ptr) const { 18 | DeleteFunc(ptr); 19 | } 20 | }; 21 | 22 | } 23 | 24 | template 25 | using sdl_ptr = std::unique_ptr>; 26 | 27 | using sdl_game_controller_ptr = sdl_ptr; 28 | using sdl_gl_context = sdl_ptr; 29 | using sdl_surface_ptr = sdl_ptr; 30 | using sdl_window_ptr = sdl_ptr; 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/shader_program.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "shader_program.hpp" 3 | 4 | #include "gl_handles.hpp" 5 | 6 | #include "SDL.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace jac { 16 | 17 | gl::shader_handle shader_program::load_shader(const std::string& filename, GLenum type) { 18 | std::fstream file{filename}; 19 | std::string data; 20 | std::copy(std::istreambuf_iterator{file}, 21 | std::istreambuf_iterator{}, 22 | std::back_inserter(data)); 23 | 24 | gl::shader_handle shader = glCreateShader(type); 25 | const char *tmp = data.data(); 26 | glShaderSource(shader.get(), 1, &tmp, nullptr); 27 | glCompileShader(shader.get()); 28 | GLint status = GL_FALSE; 29 | glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status); 30 | if (status == GL_FALSE) { 31 | std::string log; 32 | GLint len; 33 | glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &len); 34 | log.resize(len, ' '); 35 | glGetShaderInfoLog(shader.get(), len, nullptr, &log[0]); 36 | throw std::runtime_error(log); 37 | } 38 | 39 | return shader; 40 | } 41 | 42 | shader_program::shader_program(const std::string& vertex_shader_file, 43 | const std::string& fragment_shader_file) 44 | : program(glCreateProgram()), 45 | vertex_shader{load_shader(vertex_shader_file, GL_VERTEX_SHADER)}, 46 | fragment_shader{load_shader(fragment_shader_file, GL_FRAGMENT_SHADER)} 47 | { 48 | glAttachShader(program.get(), vertex_shader.get()); 49 | glAttachShader(program.get(), fragment_shader.get()); 50 | } 51 | 52 | shader_program::~shader_program() 53 | { 54 | if (program.get() != 0) { 55 | stop(); 56 | glDetachShader(program.get(), vertex_shader.get()); 57 | glDetachShader(program.get(), fragment_shader.get()); 58 | } 59 | } 60 | 61 | void shader_program::link() 62 | { 63 | bind_attributes(); 64 | glLinkProgram(program.get()); 65 | glValidateProgram(program.get()); 66 | get_all_uniform_locations(); 67 | } 68 | 69 | void shader_program::start() const 70 | { 71 | glUseProgram(program.get()); 72 | } 73 | 74 | void shader_program::stop() const 75 | { 76 | glUseProgram(0); 77 | } 78 | 79 | void shader_program::bind_attribute(GLuint attribute, 80 | const std::string& variable_name) 81 | { 82 | glBindAttribLocation(program.get(), attribute, variable_name.c_str()); 83 | } 84 | 85 | GLint shader_program::get_uniform_location(const std::string& uniform_name) const 86 | { 87 | return glGetUniformLocation(program.get(), uniform_name.c_str()); 88 | } 89 | 90 | void shader_program::load_float(GLint location, float value) const 91 | { 92 | glUniform1f(location, value); 93 | } 94 | 95 | void shader_program::load_vector(int location, const glm::vec3& vec) const 96 | { 97 | glUniform3fv(location, 1, glm::value_ptr(vec)); 98 | } 99 | 100 | void shader_program::load_bool(int location, bool value) const 101 | { 102 | float v = value ? 1.0f : 0.0f; 103 | glUniform1f(location, v); 104 | } 105 | 106 | void shader_program::load_matrix(int location, const glm::mat4& matrix) const 107 | { 108 | glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); 109 | } 110 | 111 | void shader_program::load_int(int location, int value) const 112 | { 113 | glUniform1i(location, value); 114 | } 115 | 116 | void shader_program::load_vector2d(GLint location, 117 | const glm::vec2& vector) const 118 | { 119 | glUniform2fv(location, 1, glm::value_ptr(vector)); 120 | } 121 | 122 | void shader_program::load_vector(GLint location, 123 | const glm::vec4& vector) const 124 | { 125 | glUniform4fv(location, 1, glm::value_ptr(vector)); 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/shader_program.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_SHADER_PROGRAM_HPP 3 | #define JAC_SHADER_PROGRAM_HPP 4 | 5 | #include "gl_handles.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace jac { 15 | 16 | class shader_program { 17 | public: 18 | shader_program(const std::string& vertex_shader_file, 19 | const std::string& fragment_shader_file); 20 | shader_program(shader_program&& other) 21 | : program(std::move(other.program)), 22 | vertex_shader(std::move(other.vertex_shader)), 23 | fragment_shader(std::move(other.fragment_shader)) {} 24 | 25 | shader_program& operator=(shader_program&&) = default; 26 | virtual ~shader_program(); 27 | 28 | void start() const; 29 | void stop() const; 30 | 31 | protected: 32 | void link(); 33 | virtual void bind_attributes() = 0; 34 | virtual void get_all_uniform_locations() = 0; 35 | void bind_attribute(GLuint attribute, const std::string& variable_name); 36 | GLint get_uniform_location(const std::string& uniform_name) const; 37 | void load_float(GLint location, float value) const; 38 | void load_vector(GLint location, const glm::vec3& vector) const; 39 | void load_vector2d(GLint location, const glm::vec2& vector) const; 40 | void load_bool(GLint location, bool value) const; 41 | void load_matrix(GLint location, const glm::mat4& matrix) const; 42 | void load_int(GLint location, int value) const; 43 | void load_vector(GLint location, const glm::vec4& vector) const; 44 | 45 | private: 46 | gl::shader_handle load_shader(const std::string& filename, GLenum type); 47 | 48 | gl::program_handle program; 49 | gl::shader_handle vertex_shader; 50 | gl::shader_handle fragment_shader; 51 | }; 52 | 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/shaders/fragment_shader.frag: -------------------------------------------------------------------------------- 1 | 2 | #version 330 core 3 | 4 | const int numLights = 4; 5 | 6 | in vec2 pass_textureCoords; 7 | in vec3 surfaceNormal; 8 | in vec3 toLightVector[numLights]; 9 | in vec3 toCameraVector; 10 | in float visibility; 11 | 12 | out vec4 out_colour; 13 | 14 | uniform sampler2D textureSampler; 15 | uniform vec3 lightColour[numLights]; 16 | uniform vec3 attenuation[numLights]; 17 | uniform float shineDamper; 18 | uniform float reflectivity; 19 | uniform vec3 skyColour; 20 | 21 | void main(void) 22 | { 23 | vec4 textureColour = texture(textureSampler, pass_textureCoords); 24 | if (textureColour.a < 0.5) { 25 | discard; 26 | } 27 | 28 | vec3 unitNormal = normalize(surfaceNormal); 29 | vec3 unitVectorToCamera = normalize(toCameraVector); 30 | 31 | vec3 totalDiffuse = vec3(0.0f); 32 | vec3 totalSpecular = vec3(0.0f); 33 | 34 | for (int i = 0; i < numLights; i++) { 35 | float distance = length(toLightVector[i]); 36 | float attFactor = attenuation[i].x + attenuation[i].y * distance + attenuation[i].z * distance * distance; 37 | vec3 unitLightVector = normalize(toLightVector[i]); 38 | float nDotl = dot(unitNormal, unitLightVector); 39 | float brightness = max(nDotl, 0.0f); 40 | vec3 lightDirection = -unitLightVector; 41 | vec3 reflectedLightDirection = reflect(lightDirection, unitNormal); 42 | float specularFactor = dot(reflectedLightDirection, unitVectorToCamera); 43 | specularFactor = max(specularFactor, 0.0); 44 | float dampedFactor = pow(specularFactor, shineDamper); 45 | vec3 diffuse = brightness * lightColour[i]/attFactor; 46 | totalDiffuse += diffuse; 47 | vec3 specular = dampedFactor * reflectivity * lightColour[i]/attFactor; 48 | totalSpecular += specular; 49 | } 50 | totalDiffuse = max(totalDiffuse, 0.4); 51 | 52 | out_colour = vec4(totalDiffuse, 1.0) * textureColour + vec4(totalSpecular, 1.0); 53 | out_colour = mix(vec4(skyColour, 1.0), out_colour, visibility); 54 | } 55 | -------------------------------------------------------------------------------- /src/shaders/gui_fragment_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 textureCoords; 4 | 5 | out vec4 out_Color; 6 | 7 | uniform sampler2D guiTexture; 8 | 9 | void main(void){ 10 | out_Color = texture(guiTexture, textureCoords); 11 | } -------------------------------------------------------------------------------- /src/shaders/gui_vertex_shader.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 position; 4 | 5 | out vec2 textureCoords; 6 | 7 | uniform mat4 transformationMatrix; 8 | 9 | void main(void) { 10 | gl_Position = transformationMatrix * vec4(position, 0.0, 1.0); 11 | textureCoords = vec2((position.x+1.0)/2.0, 1 - (position.y+1.0)/2.0); 12 | } 13 | -------------------------------------------------------------------------------- /src/shaders/skybox_fragment_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec3 textureCoords; 4 | out vec4 out_Color; 5 | 6 | uniform samplerCube cubeMap; 7 | uniform samplerCube cubeMap2; 8 | uniform float blendFactor; 9 | uniform vec3 fogColour; 10 | 11 | const float lowerLimit = 0.0; 12 | const float upperLimit = 30.0; 13 | 14 | void main(void) { 15 | vec4 texture1 = texture(cubeMap, textureCoords); 16 | vec4 texture2 = texture(cubeMap2, textureCoords); 17 | vec4 finalColour = mix(texture1, texture2, blendFactor); 18 | 19 | float factor = (textureCoords.y - lowerLimit)/(upperLimit - lowerLimit); 20 | factor = clamp(factor, 0.0, 1.0); 21 | out_Color = mix(vec4(fogColour, 1.0), finalColour, factor); 22 | } -------------------------------------------------------------------------------- /src/shaders/skybox_vertex_shader.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec3 position; 4 | out vec3 textureCoords; 5 | 6 | uniform mat4 projectionMatrix; 7 | uniform mat4 viewMatrix; 8 | 9 | void main(void) { 10 | gl_Position = projectionMatrix * viewMatrix * vec4(position, 1.0); 11 | textureCoords = position; 12 | } -------------------------------------------------------------------------------- /src/shaders/terrain_fragment_shader.frag: -------------------------------------------------------------------------------- 1 | 2 | #version 330 core 3 | 4 | const int numLights = 4; 5 | 6 | in vec2 pass_textureCoords; 7 | in vec3 surfaceNormal; 8 | in vec3 toLightVector[numLights]; 9 | in vec3 toCameraVector; 10 | in float visibility; 11 | 12 | out vec4 out_colour; 13 | 14 | uniform sampler2D backgroundTexture; 15 | uniform sampler2D rTexture; 16 | uniform sampler2D gTexture; 17 | uniform sampler2D bTexture; 18 | uniform sampler2D blendMap; 19 | 20 | uniform vec3 lightColour[numLights]; 21 | uniform vec3 attenuation[numLights]; 22 | uniform float shineDamper; 23 | uniform float reflectivity; 24 | uniform vec3 skyColour; 25 | 26 | void main(void) 27 | { 28 | vec4 blendMapColour = texture(blendMap, pass_textureCoords); 29 | 30 | float backTextureAmount = 1 - (blendMapColour.r + blendMapColour.g + blendMapColour.b); 31 | vec2 tiledCoords = pass_textureCoords * 40.0f; 32 | vec4 backgroundTextureColour = texture(backgroundTexture, tiledCoords) * backTextureAmount; 33 | vec4 rTextureColour = texture(rTexture, tiledCoords) * blendMapColour.r; 34 | vec4 gTextureColour = texture(gTexture, tiledCoords) * blendMapColour.g; 35 | vec4 bTextureColour = texture(bTexture, tiledCoords) * blendMapColour.b; 36 | 37 | vec4 totalColour = backgroundTextureColour + rTextureColour 38 | + gTextureColour + bTextureColour; 39 | vec3 unitNormal = normalize(surfaceNormal); 40 | vec3 unitVectorToCamera = normalize(toCameraVector); 41 | vec3 totalDiffuse = vec3(0.0f); 42 | vec3 totalSpecular = vec3(0.0f); 43 | 44 | for (int i = 0; i < numLights; i++) { 45 | float distance = length(toLightVector[i]); 46 | float attFactor = attenuation[i].x + attenuation[i].y * distance + attenuation[i].z * distance * distance; 47 | vec3 unitLightVector = normalize(toLightVector[i]); 48 | 49 | float nDotl = dot(unitNormal, unitLightVector); 50 | float brightness = max(nDotl, 0.0f); 51 | vec3 diffuse = brightness * lightColour[i]/attFactor; 52 | totalDiffuse = totalDiffuse + diffuse; 53 | 54 | vec3 lightDirection = -unitLightVector; 55 | vec3 reflectedLightDirection = reflect(lightDirection, unitNormal); 56 | 57 | float specularFactor = dot(reflectedLightDirection, unitVectorToCamera); 58 | specularFactor = max(specularFactor, 0.0); 59 | float dampedFactor = pow(specularFactor, shineDamper); 60 | vec3 finalSpecular = (dampedFactor * reflectivity * lightColour[i])/attFactor; 61 | totalSpecular += finalSpecular; 62 | } 63 | totalDiffuse = max(totalDiffuse, 0.4); 64 | 65 | out_colour = vec4(totalDiffuse, 1.0) * totalColour + vec4(totalSpecular, 1.0); 66 | out_colour = mix(vec4(skyColour, 1.0), out_colour, visibility); 67 | } 68 | -------------------------------------------------------------------------------- /src/shaders/terrain_vertex_shader.vert: -------------------------------------------------------------------------------- 1 | 2 | #version 330 core 3 | 4 | const int numLights = 4; 5 | 6 | in vec3 position; 7 | in vec2 textureCoords; 8 | in vec3 normal; 9 | 10 | out vec2 pass_textureCoords; 11 | out vec3 surfaceNormal; 12 | out vec3 toLightVector[numLights]; 13 | out vec3 toCameraVector; 14 | out float visibility; 15 | 16 | uniform mat4 transformationMatrix; 17 | uniform mat4 projectionMatrix; 18 | uniform mat4 viewMatrix; 19 | uniform vec3 lightPosition[numLights]; 20 | 21 | const float density = 0.0035f; 22 | const float gradient = 5.0f; 23 | 24 | uniform vec4 plane; 25 | 26 | void main(void) 27 | { 28 | vec4 worldPosition = transformationMatrix * vec4(position, 1.0); 29 | 30 | gl_ClipDistance[0] = dot(worldPosition, plane); 31 | 32 | vec4 positionRelativeToCam = viewMatrix * worldPosition; 33 | gl_Position = projectionMatrix * positionRelativeToCam; 34 | pass_textureCoords = textureCoords; 35 | 36 | surfaceNormal = (transformationMatrix * vec4(normal, 0.0)).xyz; 37 | for (int i = 0; i < numLights; i++) { 38 | toLightVector[i] = lightPosition[i] - worldPosition.xyz; 39 | } 40 | toCameraVector = (inverse(viewMatrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - worldPosition.xyz; 41 | 42 | float distance = length(positionRelativeToCam.xyz); 43 | visibility = exp(-pow((distance * density), gradient)); 44 | visibility = clamp(visibility, 0.0, 1.0); 45 | } 46 | -------------------------------------------------------------------------------- /src/shaders/vertex_shader.vert: -------------------------------------------------------------------------------- 1 | 2 | #version 330 core 3 | 4 | const int numLights = 4; 5 | 6 | in vec3 position; 7 | in vec2 textureCoords; 8 | in vec3 normal; 9 | 10 | out vec2 pass_textureCoords; 11 | out vec3 surfaceNormal; 12 | out vec3 toLightVector[numLights]; 13 | out vec3 toCameraVector; 14 | out float visibility; 15 | 16 | uniform mat4 transformationMatrix; 17 | uniform mat4 projectionMatrix; 18 | uniform mat4 viewMatrix; 19 | uniform vec3 lightPosition[numLights]; 20 | 21 | uniform bool useFakeLighting; 22 | 23 | uniform float numberOfRows; 24 | uniform vec2 offset; 25 | 26 | const float density = 0.0035f; 27 | const float gradient = 5.0f; 28 | 29 | uniform vec4 plane; 30 | 31 | void main(void) 32 | { 33 | vec4 worldPosition = transformationMatrix * vec4(position, 1.0); 34 | 35 | gl_ClipDistance[0] = dot(worldPosition, plane); 36 | 37 | vec4 positionRelativeToCam = viewMatrix * worldPosition; 38 | gl_Position = projectionMatrix * positionRelativeToCam; 39 | pass_textureCoords = (textureCoords/numberOfRows) + offset; 40 | 41 | vec3 actualNormal = normal; 42 | 43 | if (useFakeLighting) { 44 | actualNormal = vec3(0, 1, 0); 45 | } 46 | 47 | surfaceNormal = (transformationMatrix * vec4(actualNormal, 0.0)).xyz; 48 | for (int i = 0; i < numLights; i++) { 49 | toLightVector[i] = lightPosition[i] - worldPosition.xyz; 50 | } 51 | toCameraVector = (inverse(viewMatrix) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - worldPosition.xyz; 52 | 53 | float distance = length(positionRelativeToCam.xyz); 54 | visibility = exp(-pow((distance * density), gradient)); 55 | visibility = clamp(visibility, 0.0, 1.0); 56 | } 57 | -------------------------------------------------------------------------------- /src/shaders/water_fragment_shader.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | out vec4 out_Color; 4 | 5 | in vec4 clipSpace; 6 | in vec2 textureCoords; 7 | in vec3 toCameraVector; 8 | in vec3 fromLightVector; 9 | 10 | uniform sampler2D reflectionTexture; 11 | uniform sampler2D refractionTexture; 12 | uniform sampler2D dudvMap; 13 | uniform sampler2D normalMap; 14 | uniform sampler2D depthMap; 15 | uniform vec3 lightColour; 16 | 17 | uniform float moveFactor; 18 | 19 | const float waveStrength = 0.04; 20 | const float shineDamper = 20.0; 21 | const float reflectivity = 0.5; 22 | const float near = 0.1f; 23 | const float far = 1000.0f; 24 | 25 | void main(void) { 26 | 27 | vec2 ndc = (clipSpace.xy/clipSpace.w)/2.0 + 0.5; 28 | vec2 refractTexCoords = ndc; 29 | vec2 reflectTexCoords = vec2(ndc.x, -ndc.y); 30 | 31 | 32 | float depth = texture(depthMap, refractTexCoords).r; 33 | float floorDistance = 2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near)); 34 | 35 | depth = gl_FragCoord.z; 36 | float waterDistance = 2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near)); 37 | float waterDepth = floorDistance - waterDistance; 38 | 39 | vec2 distortedTexCoords = texture(dudvMap, vec2(textureCoords.x + moveFactor, textureCoords.y)).rg*0.1; 40 | distortedTexCoords = textureCoords + vec2(distortedTexCoords.x, distortedTexCoords.y+moveFactor); 41 | vec2 totalDistortion = (texture(dudvMap, distortedTexCoords).rg * 2.0 - 1.0) * waveStrength * clamp(waterDepth/20.0, 0.0, 1.0); 42 | 43 | refractTexCoords += totalDistortion; 44 | refractTexCoords = clamp(refractTexCoords, 0.001, 0.999); 45 | 46 | reflectTexCoords += totalDistortion; 47 | reflectTexCoords.x = clamp(reflectTexCoords.x, 0.001, 0.999); 48 | reflectTexCoords.y = clamp(reflectTexCoords.y, -0.999, -0.001); 49 | 50 | vec4 reflectColour = texture(reflectionTexture, reflectTexCoords); 51 | vec4 refractColour = texture(refractionTexture, refractTexCoords); 52 | 53 | vec4 normalMapColour = texture(normalMap, distortedTexCoords); 54 | vec3 normal = vec3(normalMapColour.r * 2.0 - 1.0, normalMapColour.b * 3.0, normalMapColour.g * 2.0 - 1.0); 55 | normal = normalize(normal); 56 | 57 | vec3 viewVector = normalize(toCameraVector); 58 | float refractFactor = dot(viewVector, normal); 59 | refractFactor = pow(refractFactor, 0.5); 60 | 61 | vec3 reflectedLight = reflect(normalize(fromLightVector), normal); 62 | float specular = max(dot(reflectedLight, viewVector), 0.0); 63 | specular = pow(specular, shineDamper); 64 | vec3 specularHighlights = lightColour * specular * reflectivity * clamp(waterDepth/5.0, 0.0, 1.0); 65 | 66 | out_Color = mix(reflectColour, refractColour, refractFactor); 67 | out_Color = mix(out_Color, vec4(0.0, 0.3, 0.5, 1.0), 0.2) + vec4(specularHighlights, 0.0); 68 | out_Color.a = clamp(waterDepth/5.0, 0.0, 1.0); 69 | } -------------------------------------------------------------------------------- /src/shaders/water_vertex_shader.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 position; 4 | 5 | out vec4 clipSpace; 6 | out vec2 textureCoords; 7 | out vec3 toCameraVector; 8 | out vec3 fromLightVector; 9 | 10 | uniform mat4 projectionMatrix; 11 | uniform mat4 viewMatrix; 12 | uniform mat4 modelMatrix; 13 | uniform vec3 cameraPosition; 14 | uniform vec3 lightPosition; 15 | 16 | const float tiling = 4.0; 17 | 18 | void main(void) { 19 | vec4 worldPosition = modelMatrix * vec4(position.x, 0.0, position.y, 1.0); 20 | clipSpace = projectionMatrix * viewMatrix * worldPosition; 21 | gl_Position = clipSpace; 22 | textureCoords = vec2(position.x/2.0 + 0.5, position.y/2.0 + 0.5) * tiling; 23 | toCameraVector = cameraPosition - worldPosition.xyz; 24 | fromLightVector = worldPosition.xyz - lightPosition; 25 | } -------------------------------------------------------------------------------- /src/skybox_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "skybox_renderer.hpp" 3 | 4 | #include "camera.hpp" 5 | #include "loader.hpp" 6 | #include "display_manager.hpp" 7 | 8 | #include 9 | #include 10 | 11 | namespace { 12 | 13 | constexpr float SIZE = 500.0f; 14 | 15 | constexpr float VERTICES[] = { 16 | -SIZE, SIZE, -SIZE, 17 | -SIZE, -SIZE, -SIZE, 18 | SIZE, -SIZE, -SIZE, 19 | SIZE, -SIZE, -SIZE, 20 | SIZE, SIZE, -SIZE, 21 | -SIZE, SIZE, -SIZE, 22 | 23 | -SIZE, -SIZE, SIZE, 24 | -SIZE, -SIZE, -SIZE, 25 | -SIZE, SIZE, -SIZE, 26 | -SIZE, SIZE, -SIZE, 27 | -SIZE, SIZE, SIZE, 28 | -SIZE, -SIZE, SIZE, 29 | 30 | SIZE, -SIZE, -SIZE, 31 | SIZE, -SIZE, SIZE, 32 | SIZE, SIZE, SIZE, 33 | SIZE, SIZE, SIZE, 34 | SIZE, SIZE, -SIZE, 35 | SIZE, -SIZE, -SIZE, 36 | 37 | -SIZE, -SIZE, SIZE, 38 | -SIZE, SIZE, SIZE, 39 | SIZE, SIZE, SIZE, 40 | SIZE, SIZE, SIZE, 41 | SIZE, -SIZE, SIZE, 42 | -SIZE, -SIZE, SIZE, 43 | 44 | -SIZE, SIZE, -SIZE, 45 | SIZE, SIZE, -SIZE, 46 | SIZE, SIZE, SIZE, 47 | SIZE, SIZE, SIZE, 48 | -SIZE, SIZE, SIZE, 49 | -SIZE, SIZE, -SIZE, 50 | 51 | -SIZE, -SIZE, -SIZE, 52 | -SIZE, -SIZE, SIZE, 53 | SIZE, -SIZE, -SIZE, 54 | SIZE, -SIZE, -SIZE, 55 | -SIZE, -SIZE, SIZE, 56 | SIZE, -SIZE, SIZE 57 | }; 58 | 59 | constexpr const char * const texture_files[] = { 60 | "right", 61 | "left", 62 | "top", 63 | "bottom", 64 | "back", 65 | "front" 66 | }; 67 | 68 | constexpr const char* const night_texture_files[] = { 69 | "nightRight", 70 | "nightLeft", 71 | "nightTop", 72 | "nightBottom", 73 | "nightBack", 74 | "nightFront" 75 | }; 76 | 77 | } 78 | 79 | namespace jac { 80 | 81 | skybox_renderer::skybox_renderer(loader& loader, const glm::mat4& matrix) 82 | : cube{loader.load_to_vao(std::vector(std::begin(VERTICES), 83 | std::end(VERTICES)), 3)}, 84 | texture_id{loader.load_cube_map(std::vector(std::begin(texture_files), 85 | std::end(texture_files)))}, 86 | night_texture_id{loader.load_cube_map(std::vector(std::begin(night_texture_files), 87 | std::end(night_texture_files)))} 88 | { 89 | shader.start(); 90 | shader.connect_texture_units(); 91 | shader.load_projection_matrix(matrix); 92 | shader.stop(); 93 | } 94 | 95 | void skybox_renderer::render(const camera& cam, float r, float g, float b) 96 | { 97 | shader.start(); 98 | shader.load_view_matrix(cam); 99 | shader.load_fog_colour(r, g, b); 100 | glBindVertexArray(cube.vao_id); 101 | glEnableVertexAttribArray(0); 102 | bind_textures(); 103 | glDrawArrays(GL_TRIANGLES, 0, cube.vertex_count); 104 | glDisableVertexAttribArray(0); 105 | glBindVertexArray(0); 106 | shader.stop(); 107 | } 108 | 109 | 110 | void skybox_renderer::bind_textures() 111 | { 112 | time += get_frame_time_seconds().count() * 1000; 113 | time = std::fmod(time, 24000); 114 | GLuint texture1; 115 | GLuint texture2; 116 | float blendFactor = 0.0; 117 | #if 0 118 | if(time >= 0 && time < 5000){ 119 | texture1 = night_texture_id; 120 | texture2 = night_texture_id; 121 | blendFactor = (time - 0)/(5000 - 0); 122 | }else if(time >= 5000 && time < 8000){ 123 | texture1 = night_texture_id; 124 | texture2 = texture_id; 125 | blendFactor = (time - 5000)/(8000 - 5000); 126 | }else if(time >= 8000 && time < 21000){ 127 | texture1 = texture_id; 128 | texture2 = texture_id; 129 | blendFactor = (time - 8000)/(21000 - 8000); 130 | }else{ 131 | texture1 = texture_id; 132 | texture2 = night_texture_id; 133 | blendFactor = (time - 21000)/(24000 - 21000); 134 | } 135 | #endif 136 | texture1 = texture_id; 137 | texture2 = texture_id; 138 | glActiveTexture(GL_TEXTURE0); 139 | glBindTexture(GL_TEXTURE_CUBE_MAP, texture1); 140 | glActiveTexture(GL_TEXTURE1); 141 | glBindTexture(GL_TEXTURE_CUBE_MAP, texture2); 142 | shader.load_blend_factor(blendFactor); 143 | } 144 | 145 | 146 | } -------------------------------------------------------------------------------- /src/skybox_renderer.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_SKYBOX_RENDERER_HPP 3 | #define JAC_SKYBOX_RENDERER_HPP 4 | 5 | #include "raw_model.hpp" 6 | #include "skybox_shader.hpp" 7 | 8 | namespace jac { 9 | 10 | class loader; 11 | 12 | class skybox_renderer 13 | { 14 | public: 15 | skybox_renderer(loader& loader, const glm::mat4& matrix); 16 | 17 | void render(const camera& cam, float r, float g, float b); 18 | 19 | private: 20 | void bind_textures(); 21 | 22 | raw_model cube{}; 23 | unsigned texture_id = 0; 24 | unsigned night_texture_id = 0; 25 | skybox_shader shader{}; 26 | float time = 0.0f; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/skybox_shader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "skybox_shader.hpp" 3 | 4 | #include "display_manager.hpp" 5 | #include "camera.hpp" 6 | #include "maths.hpp" 7 | 8 | #include "SDL.h" 9 | 10 | #include 11 | 12 | constexpr char vertex_shader_source[] = "shaders/skybox_vertex_shader.vert"; 13 | constexpr char fragment_shader_source[] = "shaders/skybox_fragment_shader.frag"; 14 | 15 | constexpr float rotate_speed = 1.0f; 16 | 17 | namespace jac { 18 | 19 | skybox_shader::skybox_shader() 20 | : shader_program(vertex_shader_source, fragment_shader_source) 21 | { 22 | link(); 23 | } 24 | 25 | void skybox_shader::bind_attributes() 26 | { 27 | bind_attribute(0, "position"); 28 | } 29 | 30 | void skybox_shader::get_all_uniform_locations() 31 | { 32 | location_projection_matrix = get_uniform_location("projectionMatrix"); 33 | location_view_matrix = get_uniform_location("viewMatrix"); 34 | location_fog_colour = get_uniform_location("fogColour"); 35 | location_cube_map = get_uniform_location("cubeMap"); 36 | location_cube_map2 = get_uniform_location("cubeMap2"); 37 | location_blend_factor = get_uniform_location("blendFactor"); 38 | } 39 | 40 | void skybox_shader::load_projection_matrix(const glm::mat4& matrix) const 41 | { 42 | load_matrix(location_projection_matrix, matrix); 43 | } 44 | 45 | void skybox_shader::load_view_matrix(const camera& cam) 46 | { 47 | auto matrix = maths::create_view_matrix(cam); 48 | matrix[3] = glm::vec4{0.0, 0.0, 0.0, matrix[3][3]}; 49 | rotation += rotate_speed * get_frame_time_seconds().count(); 50 | matrix = glm::rotate(matrix, glm::radians(rotation), {0, 1, 0}); 51 | load_matrix(location_view_matrix, matrix); 52 | } 53 | 54 | void skybox_shader::load_fog_colour(float r, float g, float b) const 55 | { 56 | load_vector(location_fog_colour, {r, g, b}); 57 | } 58 | 59 | void skybox_shader::load_blend_factor(float factor) const 60 | { 61 | load_float(location_blend_factor, factor); 62 | } 63 | 64 | void skybox_shader::connect_texture_units() const 65 | { 66 | load_int(location_cube_map, 0); 67 | load_int(location_cube_map2, 1); 68 | } 69 | 70 | 71 | } -------------------------------------------------------------------------------- /src/skybox_shader.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_SKYBOX_SHADER_HPP 3 | #define JAC_SKYBOX_SHADER_HPP 4 | 5 | #include "shader_program.hpp" 6 | 7 | namespace jac { 8 | 9 | class camera; 10 | 11 | class skybox_shader final : public shader_program 12 | { 13 | public: 14 | skybox_shader(); 15 | 16 | void load_projection_matrix(const glm::mat4& matrix) const; 17 | 18 | void load_view_matrix(const camera& matrix); 19 | 20 | void load_fog_colour(float r, float g, float b) const; 21 | 22 | void load_blend_factor(float factor) const; 23 | 24 | void connect_texture_units() const; 25 | 26 | private: 27 | virtual void bind_attributes() override; 28 | virtual void get_all_uniform_locations() override; 29 | 30 | float rotation = 0.0f; 31 | 32 | int location_projection_matrix = 0; 33 | int location_view_matrix = 0; 34 | int location_fog_colour = 0; 35 | int location_cube_map = 0; 36 | int location_cube_map2 = 0; 37 | int location_blend_factor = 0; 38 | }; 39 | 40 | 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/static_shader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "static_shader.hpp" 3 | 4 | #include "light.hpp" 5 | #include "maths.hpp" 6 | 7 | constexpr char vertex_shader_source[] = "shaders/vertex_shader.vert"; 8 | constexpr char fragment_shader_source[] = "shaders/fragment_shader.frag"; 9 | 10 | namespace jac { 11 | 12 | static_shader::static_shader() 13 | : shader_program{vertex_shader_source, fragment_shader_source} 14 | { 15 | link(); 16 | } 17 | 18 | void static_shader::bind_attributes() 19 | { 20 | bind_attribute(0, "position"); 21 | bind_attribute(1, "textureCoords"); 22 | bind_attribute(2, "normal"); 23 | } 24 | 25 | void static_shader::get_all_uniform_locations() 26 | { 27 | location_transformation_matrix = get_uniform_location("transformationMatrix"); 28 | location_projection_matrix = get_uniform_location("projectionMatrix"); 29 | location_view_matrix = get_uniform_location("viewMatrix"); 30 | location_shine_damper = get_uniform_location("shineDamper"); 31 | location_reflectivity = get_uniform_location("reflectivity"); 32 | location_use_fake_lighting = get_uniform_location("useFakeLighting"); 33 | location_sky_colour = get_uniform_location("skyColour"); 34 | location_number_of_rows = get_uniform_location("numberOfRows"); 35 | location_offset = get_uniform_location("offset"); 36 | location_plane = get_uniform_location("plane"); 37 | 38 | for (int i = 0; i < max_lights; i++) { 39 | auto i_s = std::to_string(i); 40 | location_light_position[i] = get_uniform_location("lightPosition[" + i_s + "]"); 41 | location_light_colour[i] = get_uniform_location("lightColour[" + i_s + "]"); 42 | location_attenuation[i] = get_uniform_location("attenuation[" + i_s + "]"); 43 | } 44 | } 45 | 46 | void static_shader::load_transformation_matrix(const glm::mat4& matrix) const 47 | { 48 | load_matrix(location_transformation_matrix, matrix); 49 | } 50 | 51 | void static_shader::load_lights(const std::vector& lights) const 52 | { 53 | for (int i = 0; i < max_lights; i++) { 54 | if (i < lights.size()) { 55 | load_vector(location_light_position[i], lights[i].position); 56 | load_vector(location_light_colour[i], lights[i].colour); 57 | load_vector(location_attenuation[i], lights[i].attenuation); 58 | } else { 59 | load_vector(location_light_position[i], glm::vec3{0, 0, 0}); 60 | load_vector(location_light_position[i], glm::vec3{0, 0, 0}); 61 | load_vector(location_light_position[i], glm::vec3{1, 0, 0}); 62 | } 63 | } 64 | } 65 | 66 | void static_shader::load_view_matrix(const camera& camera) const 67 | { 68 | load_matrix(location_view_matrix, maths::create_view_matrix(camera)); 69 | } 70 | 71 | void static_shader::load_projection_matrix(const glm::mat4& projection) const 72 | { 73 | load_matrix(location_projection_matrix, projection); 74 | } 75 | 76 | void static_shader::load_shine_variables(float damper, float reflectivity) const 77 | { 78 | load_float(location_shine_damper, damper); 79 | load_float(location_reflectivity, reflectivity); 80 | } 81 | 82 | void static_shader::load_fake_lighting_variable(bool use_fake) const 83 | { 84 | load_bool(location_use_fake_lighting, use_fake); 85 | } 86 | 87 | void static_shader::load_sky_colour(float r, float g, float b) const 88 | { 89 | load_vector(location_sky_colour, {r, g, b}); 90 | } 91 | 92 | void static_shader::load_number_of_rows(int num_rows) const 93 | { 94 | load_float(location_number_of_rows, num_rows); 95 | } 96 | 97 | void static_shader::load_offset(float x_offset, float y_offset) const 98 | { 99 | load_vector2d(location_offset, glm::vec2{x_offset, y_offset}); 100 | } 101 | 102 | void static_shader::load_clip_plane(const glm::vec4& plane) const 103 | { 104 | load_vector(location_plane, plane); 105 | } 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/static_shader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_STATIC_SHADER_HPP 2 | #define JAC_STATIC_SHADER_HPP 3 | 4 | #include "shader_program.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace jac { 10 | 11 | class camera; 12 | struct light; 13 | 14 | class static_shader final : public shader_program 15 | { 16 | public: 17 | static_shader(); 18 | 19 | void load_transformation_matrix(const glm::mat4& matrix) const; 20 | void load_projection_matrix(const glm::mat4& projection) const; 21 | void load_view_matrix(const camera& camera) const; 22 | void load_lights(const std::vector& lights) const; 23 | void load_shine_variables(float damper, float reflectivity) const; 24 | void load_fake_lighting_variable(bool use_fake) const; 25 | void load_sky_colour(float r, float g, float b) const; 26 | void load_number_of_rows(int num_rows) const; 27 | void load_offset(float x_offset, float y_offset) const; 28 | void load_clip_plane(const glm::vec4& plane) const; 29 | 30 | private: 31 | virtual void bind_attributes() override; 32 | virtual void get_all_uniform_locations() override; 33 | 34 | static constexpr int max_lights = 4; 35 | 36 | int location_transformation_matrix = 0; 37 | int location_projection_matrix = 0; 38 | int location_view_matrix = 0; 39 | int location_light_position[max_lights] = { 0, }; 40 | int location_light_colour[max_lights] = { 0, }; 41 | int location_attenuation[max_lights] = { 0, }; 42 | int location_shine_damper = 0; 43 | int location_reflectivity = 0; 44 | int location_use_fake_lighting = 0; 45 | int location_sky_colour = 0; 46 | int location_number_of_rows = 0; 47 | int location_offset = 0; 48 | int location_plane = 0; 49 | }; 50 | 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/stb_image.c: -------------------------------------------------------------------------------- 1 | 2 | #define STB_IMAGE_IMPLEMENTATION 3 | #include 4 | -------------------------------------------------------------------------------- /src/stb_image.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef STB_IMAGE_CPP_HEADER 3 | #define STB_IMAGE_CPP_HEADER 4 | 5 | #include "stb_image.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace stb { 12 | 13 | class image { 14 | public: 15 | explicit image(const char* filename, int num_components = 0) 16 | : data_{stbi_load(filename, &w, &h, &comp, num_components)} 17 | {} 18 | 19 | explicit image(const std::string& filename, int num_components = 0) 20 | : image(filename.c_str(), num_components) 21 | {} 22 | 23 | 24 | int width() const { return w; } 25 | 26 | int height() const { return h; } 27 | 28 | int num_components() const { return comp; } 29 | 30 | std::uint32_t get_rgb(int x, int y) const 31 | { 32 | int addr = (y * w + x) * comp; 33 | std::uint32_t r = data_[addr]; 34 | std::uint32_t g = data_[addr + 1]; 35 | std::uint32_t b = data_[addr + 2]; 36 | return (r << 16) + (g << 8) + b; 37 | } 38 | 39 | const std::uint8_t* data() const { return data_.get(); } 40 | 41 | explicit operator bool() { return bool(data_); } 42 | 43 | private: 44 | struct deleter { 45 | void operator()(unsigned char* data) const { 46 | stbi_image_free(data); 47 | } 48 | }; 49 | 50 | int w = 0; 51 | int h = 0; 52 | int comp = 0; 53 | 54 | std::unique_ptr data_ = nullptr; 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/terrain.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "terrain.hpp" 3 | 4 | #include "loader.hpp" 5 | #include "sdl_handles.hpp" 6 | #include "stb_image.hpp" 7 | #include "maths.hpp" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace { 16 | 17 | constexpr float size = 800.0f; 18 | constexpr float max_height = 40.0f; 19 | constexpr std::uint32_t max_pixel_colour = 256 * 256 * 256; 20 | 21 | 22 | float get_height(int x, int z, const stb::image& image) 23 | { 24 | if (x < 0 || x > image.height() || z < 0 || z > image.height()) { 25 | return 0; 26 | } 27 | 28 | uint32_t val = image.get_rgb(x, z); 29 | 30 | double height = val; 31 | height /= (max_pixel_colour/2); 32 | height -= 1.0; 33 | height *= max_height; 34 | //std::cout << height << std::endl; 35 | 36 | return height; 37 | } 38 | 39 | 40 | glm::vec3 calculate_normal(int x, int z, const stb::image& image) 41 | { 42 | float height_l = get_height(x - 1, z, image); 43 | float height_r = get_height(x + 1, z, image); 44 | float height_d = get_height(x, z - 1, image); 45 | float height_u = get_height(x, z + 1, image); 46 | 47 | glm::vec3 normal{height_l - height_r, 2.0f, height_d - height_u}; 48 | normal = glm::normalize(normal); 49 | 50 | return normal; 51 | } 52 | 53 | } // end anonymous namespace 54 | 55 | 56 | 57 | 58 | 59 | namespace jac { 60 | 61 | terrain::terrain(int grid_x, int grid_z, loader& loader, 62 | terrain_texture_pack texture_pack, 63 | terrain_texture blend_map, 64 | const std::string& heightmap) 65 | : x{grid_x * size}, 66 | z{grid_z * size}, 67 | model{generate_terrain(loader, heightmap)}, 68 | texture_pack{std::move(texture_pack)}, 69 | blend_map{std::move(blend_map)} 70 | {} 71 | 72 | jac::raw_model terrain::generate_terrain(jac::loader& loader, 73 | const std::string& heightmap) 74 | { 75 | stb::image image{"res/" + heightmap + ".png", 4}; 76 | int vertex_count = image.height(); 77 | heights.resize(vertex_count); 78 | for (auto& h : heights) h.resize(vertex_count); 79 | 80 | int count = vertex_count * vertex_count; 81 | auto vertices = std::vector(count * 3); 82 | auto normals = std::vector(count * 3); 83 | auto textureCoords = std::vector(count * 2); 84 | auto indices = std::vector(6*(vertex_count-1)*(vertex_count-1)); 85 | int vertexPointer = 0; 86 | 87 | for(int i=0;i heights.size() - 1 || grid_z > heights.size() - 1 || 130 | grid_x < 0 || grid_z < 0) { 131 | return 0; 132 | } 133 | 134 | float x_coord = std::fmod(terrain_x, grid_square_size)/grid_square_size; 135 | float z_coord = std::fmod(terrain_z, grid_square_size)/grid_square_size; 136 | float answer = 0.0f; 137 | 138 | if (x_coord <= (1 - z_coord)) { 139 | answer = maths::barrycentric( 140 | glm::vec3{0, heights[grid_x][grid_z], 0}, 141 | glm::vec3{1, heights[grid_x + 1][grid_z], 0}, 142 | glm::vec3{0, heights[grid_x][grid_z + 1], 1}, 143 | glm::vec2{x_coord, z_coord}); 144 | } else { 145 | answer = maths::barrycentric( 146 | glm::vec3{0, heights[grid_x + 1][grid_z], 0}, 147 | glm::vec3{1, heights[grid_x + 1][grid_z + 1], 1}, 148 | glm::vec3{0, heights[grid_x][grid_z + 1], 1}, 149 | glm::vec2{x_coord, z_coord}); 150 | } 151 | 152 | return answer; 153 | } 154 | 155 | } 156 | 157 | -------------------------------------------------------------------------------- /src/terrain.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_TERRAIN_HPP 2 | #define JAC_TERRAIN_HPP 3 | 4 | #include "raw_model.hpp" 5 | #include "terrain_texture.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace jac { 11 | 12 | class loader; 13 | 14 | class terrain { 15 | public: 16 | terrain(int grid_x, int grid_z, loader& loader, 17 | terrain_texture_pack texture_pack, 18 | terrain_texture blend_map, 19 | const std::string& heightmap); 20 | 21 | float get_x() const { return x; } 22 | float get_z() const { return z; } 23 | const raw_model& get_model() const { return model; } 24 | const terrain_texture_pack& get_texture_pack() const { return texture_pack; } 25 | const terrain_texture& get_blend_map() const { return blend_map; } 26 | 27 | float get_height_of_terrain(float world_x, float world_y) const; 28 | 29 | private: 30 | raw_model generate_terrain(loader& loader, const std::string& heightmap); 31 | 32 | float x; 33 | float z; 34 | std::vector> heights; 35 | raw_model model; 36 | terrain_texture_pack texture_pack; 37 | terrain_texture blend_map; 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/terrain_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "terrain_renderer.hpp" 3 | 4 | #include "maths.hpp" 5 | #include "terrain.hpp" 6 | #include "textured_model.hpp" 7 | #include "terrain_shader.hpp" 8 | 9 | namespace jac { 10 | 11 | terrain_renderer::terrain_renderer(const terrain_shader& shader, 12 | const glm::mat4& projection_matrix) 13 | : shader{shader} 14 | { 15 | shader.start(); 16 | shader.load_projection_matrix(projection_matrix); 17 | shader.connect_texture_units(); 18 | shader.stop(); 19 | } 20 | 21 | void terrain_renderer::render(const std::vector& terrains) const 22 | { 23 | for (const auto& terrain : terrains) { 24 | prepare_terrain(*terrain); 25 | load_model_matrix(*terrain); 26 | 27 | glDrawElements(GL_TRIANGLES, terrain->get_model().vertex_count, 28 | GL_UNSIGNED_INT, 0); 29 | 30 | unbind_textured_model(); 31 | } 32 | } 33 | 34 | void terrain_renderer::prepare_terrain(const terrain& terrain) const 35 | { 36 | const auto& raw_model = terrain.get_model(); 37 | glBindVertexArray(raw_model.vao_id); 38 | glEnableVertexAttribArray(0); 39 | glEnableVertexAttribArray(1); 40 | glEnableVertexAttribArray(2); 41 | bind_textures(terrain); 42 | shader.load_shine_variables(1, 0); 43 | 44 | } 45 | 46 | void terrain_renderer::bind_textures(const terrain& terrain) const 47 | { 48 | const auto& texture_pack = terrain.get_texture_pack(); 49 | glActiveTexture(GL_TEXTURE0); 50 | glBindTexture(GL_TEXTURE_2D, texture_pack.background_texture.texture_id); 51 | glActiveTexture(GL_TEXTURE1); 52 | glBindTexture(GL_TEXTURE_2D, texture_pack.r_texture.texture_id); 53 | glActiveTexture(GL_TEXTURE2); 54 | glBindTexture(GL_TEXTURE_2D, texture_pack.g_texture.texture_id); 55 | glActiveTexture(GL_TEXTURE3); 56 | glBindTexture(GL_TEXTURE_2D, texture_pack.b_texture.texture_id); 57 | glActiveTexture(GL_TEXTURE4); 58 | glBindTexture(GL_TEXTURE_2D, terrain.get_blend_map().texture_id); 59 | } 60 | 61 | void terrain_renderer::load_model_matrix(const terrain& terrain) const 62 | { 63 | glm::mat4 transformation_matrix = maths::create_transformation_matrix( 64 | glm::vec3{terrain.get_x(), 0, terrain.get_z()}, 65 | 0.0f, 0.0f, 0.0f, 1.0f); 66 | shader.load_transformation_matrix(transformation_matrix); 67 | } 68 | 69 | void terrain_renderer::unbind_textured_model() const 70 | { 71 | glDisableVertexAttribArray(0); 72 | glDisableVertexAttribArray(1); 73 | glDisableVertexAttribArray(2); 74 | glBindVertexArray(0); 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/terrain_renderer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_TERRAIN_RENDERER_HPP 2 | #define JAC_TERRAIN_RENDERER_HPP 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace jac { 9 | 10 | class terrain; 11 | struct textured_model; 12 | class terrain_shader; 13 | 14 | class terrain_renderer { 15 | public: 16 | terrain_renderer(const terrain_shader& shader, const glm::mat4& projection_matrix); 17 | 18 | void render(const std::vector& terrains) const; 19 | 20 | private: 21 | void load_model_matrix(const terrain& terrain) const; 22 | void prepare_terrain(const terrain& terrain) const; 23 | void bind_textures(const terrain& terrain) const; 24 | void unbind_textured_model() const; 25 | 26 | const terrain_shader& shader; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/terrain_shader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "terrain_shader.hpp" 3 | 4 | #include "camera.hpp" 5 | #include "light.hpp" 6 | #include "maths.hpp" 7 | 8 | constexpr char vertex_shader_source[] = "shaders/terrain_vertex_shader.vert"; 9 | constexpr char fragment_shader_source[] = "shaders/terrain_fragment_shader.frag"; 10 | 11 | namespace jac { 12 | 13 | 14 | terrain_shader::terrain_shader() 15 | : shader_program{vertex_shader_source, fragment_shader_source} 16 | { 17 | link(); 18 | } 19 | 20 | void terrain_shader::bind_attributes() 21 | { 22 | bind_attribute(0, "position"); 23 | bind_attribute(1, "textureCoords"); 24 | bind_attribute(2, "normal"); 25 | } 26 | 27 | void terrain_shader::get_all_uniform_locations() 28 | { 29 | location_transformation_matrix = get_uniform_location("transformationMatrix"); 30 | location_projection_matrix = get_uniform_location("projectionMatrix"); 31 | location_view_matrix = get_uniform_location("viewMatrix"); 32 | location_shine_damper = get_uniform_location("shineDamper"); 33 | location_reflectivity = get_uniform_location("reflectivity"); 34 | location_sky_colour = get_uniform_location("skyColour"); 35 | location_background_texture = get_uniform_location("backgroundTexture"); 36 | location_r_texture = get_uniform_location("rTexture"); 37 | location_g_texture = get_uniform_location("gTexture"); 38 | location_b_texture = get_uniform_location("bTexture"); 39 | location_blend_map = get_uniform_location("blendMap"); 40 | location_plane = get_uniform_location("plane"); 41 | 42 | for (int i = 0; i < max_lights; i++) { 43 | const auto i_s = std::to_string(i); 44 | location_light_position[i] = get_uniform_location("lightPosition[" + i_s + "]"); 45 | location_light_colour[i] = get_uniform_location("lightColour[" + i_s + "]"); 46 | location_attenuation[i] = get_uniform_location("attenuation[" + i_s + "]"); 47 | } 48 | } 49 | 50 | void terrain_shader::load_transformation_matrix(const glm::mat4& matrix) const 51 | { 52 | load_matrix(location_transformation_matrix, matrix); 53 | } 54 | 55 | void terrain_shader::load_lights(const std::vector& lights) const 56 | { 57 | for (int i = 0; i < max_lights; i++) { 58 | if (i < lights.size()) { 59 | load_vector(location_light_position[i], lights[i].position); 60 | load_vector(location_light_colour[i], lights[i].colour); 61 | load_vector(location_attenuation[i], lights[i].attenuation); 62 | } else { 63 | load_vector(location_light_position[i], glm::vec3{0, 0, 0}); 64 | load_vector(location_light_colour[i], glm::vec3{0, 0, 0}); 65 | load_vector(location_attenuation[i], glm::vec3{1, 0, 0}); 66 | } 67 | } 68 | } 69 | 70 | void terrain_shader::load_view_matrix(const camera& camera) const 71 | { 72 | load_matrix(location_view_matrix, maths::create_view_matrix(camera)); 73 | } 74 | 75 | void terrain_shader::load_projection_matrix(const glm::mat4& projection) const 76 | { 77 | load_matrix(location_projection_matrix, projection); 78 | } 79 | 80 | void terrain_shader::load_shine_variables(float damper, float reflectivity) const 81 | { 82 | load_float(location_shine_damper, damper); 83 | load_float(location_reflectivity, reflectivity); 84 | } 85 | 86 | void terrain_shader::load_sky_colour(float r, float g, float b) const 87 | { 88 | load_vector(location_sky_colour, {r, g, b}); 89 | } 90 | 91 | void terrain_shader::connect_texture_units() const 92 | { 93 | load_int(location_background_texture, 0); 94 | load_int(location_r_texture, 1); 95 | load_int(location_g_texture, 2); 96 | load_int(location_b_texture, 3); 97 | load_int(location_blend_map, 4); 98 | } 99 | 100 | void terrain_shader::load_clip_plane(const glm::vec4& plane) const 101 | { 102 | load_vector(location_plane, plane); 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/terrain_shader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_TERRAIN_SHADER_HPP 2 | #define JAC_TERRAIN_SHADER_HPP 3 | 4 | #include "shader_program.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace jac { 10 | 11 | class camera; 12 | struct light; 13 | 14 | class terrain_shader final : public shader_program 15 | { 16 | public: 17 | terrain_shader(); 18 | 19 | void load_transformation_matrix(const glm::mat4& matrix) const; 20 | void load_projection_matrix(const glm::mat4& projection) const; 21 | void load_view_matrix(const camera& camera) const; 22 | void load_lights(const std::vector& lights) const; 23 | void load_shine_variables(float damper, float reflectivity) const; 24 | void load_sky_colour(float r, float g, float b) const; 25 | void connect_texture_units() const; 26 | void load_clip_plane(const glm::vec4& plane) const; 27 | 28 | private: 29 | virtual void bind_attributes() override; 30 | virtual void get_all_uniform_locations() override; 31 | 32 | static constexpr int max_lights = 4; 33 | 34 | int location_transformation_matrix = 0; 35 | int location_projection_matrix = 0; 36 | int location_view_matrix = 0; 37 | int location_light_position[max_lights] = { 0, }; 38 | int location_light_colour[max_lights] = { 0, }; 39 | int location_attenuation[max_lights] = { 0, }; 40 | int location_shine_damper = 0; 41 | int location_reflectivity = 0; 42 | int location_sky_colour = 0; 43 | int location_background_texture = 0; 44 | int location_r_texture = 0; 45 | int location_g_texture = 0; 46 | int location_b_texture = 0; 47 | int location_blend_map = 0; 48 | int location_plane = 0; 49 | }; 50 | 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/terrain_texture.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/src/terrain_texture.cpp -------------------------------------------------------------------------------- /src/terrain_texture.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_TERRAIN_TEXTURE_HPP 3 | #define JAC_TERRAIN_TEXTURE_HPP 4 | 5 | #include "gl_handles.hpp" 6 | 7 | namespace jac { 8 | 9 | struct terrain_texture { 10 | unsigned texture_id; 11 | }; 12 | 13 | struct terrain_texture_pack { 14 | terrain_texture background_texture; 15 | terrain_texture r_texture; 16 | terrain_texture g_texture; 17 | terrain_texture b_texture; 18 | }; 19 | 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/textured_model.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tcbrindle/thinmatrix-gl-tutorials/1758ff9130611daecc408d0c7fc8b0c48b7e8253/src/textured_model.cpp -------------------------------------------------------------------------------- /src/textured_model.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_TEXTURED_MODEL_HPP 2 | #define JAC_TEXTURED_MODEL_HPP 3 | 4 | #include "model_texture.hpp" 5 | #include "raw_model.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace jac { 11 | 12 | struct textured_model { 13 | raw_model raw{}; 14 | model_texture texture{}; 15 | }; 16 | 17 | inline bool operator==(const textured_model& lhs, const textured_model& rhs) 18 | { 19 | return lhs.raw == rhs.raw && lhs.texture == rhs.texture; 20 | } 21 | 22 | } 23 | 24 | namespace std { 25 | 26 | template <> 27 | struct hash { 28 | using argument_type = jac::textured_model; 29 | using result_type = size_t; 30 | 31 | size_t operator()(const jac::textured_model& model) const noexcept { 32 | return hash{}(model.raw) ^ 33 | hash{}(model.texture); 34 | } 35 | }; 36 | 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/water_frame_buffers.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "water_frame_buffers.hpp" 3 | 4 | #include "SDL.h" 5 | 6 | namespace jac { 7 | 8 | water_frame_buffers::water_frame_buffers() 9 | { 10 | initialise_reflection_frame_buffer(); 11 | initialise_refraction_frame_buffer(); 12 | } 13 | 14 | void water_frame_buffers::bind_reflection_frame_buffer() const 15 | { 16 | bind_frame_buffer(reflection_framebuffer.get(), reflection_width, reflection_height); 17 | } 18 | 19 | void water_frame_buffers::bind_refraction_frame_buffer() const 20 | { 21 | bind_frame_buffer(refraction_framebuffer.get(), refraction_width, refraction_height); 22 | } 23 | 24 | void water_frame_buffers::unbind_current_frame_buffer() const 25 | { 26 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 27 | 28 | int w, h; 29 | SDL_GL_GetDrawableSize(SDL_GL_GetCurrentWindow(), &w, &h); 30 | 31 | glViewport(0, 0, w, h); 32 | } 33 | 34 | void water_frame_buffers::initialise_reflection_frame_buffer() 35 | { 36 | reflection_framebuffer = create_frame_buffer(); 37 | reflection_texture = create_texture_attachment(reflection_width, reflection_height); 38 | reflection_depth_buffer = create_depth_buffer_attachment(reflection_width, reflection_height); 39 | unbind_current_frame_buffer(); 40 | } 41 | 42 | void water_frame_buffers::initialise_refraction_frame_buffer() 43 | { 44 | refraction_framebuffer = create_frame_buffer(); 45 | refraction_texture = create_texture_attachment(refraction_width, refraction_height); 46 | refraction_depth_texture = create_depth_texture_attachment(refraction_width, refraction_height); 47 | unbind_current_frame_buffer(); 48 | } 49 | 50 | void water_frame_buffers::bind_frame_buffer(GLuint framebuffer, int width, 51 | int height) const 52 | { 53 | glBindTexture(GL_TEXTURE_2D, 0); 54 | glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 55 | glViewport(0, 0, width, height); 56 | } 57 | 58 | gl::framebuffer_handle water_frame_buffers::create_frame_buffer() 59 | { 60 | gl::framebuffer_handle fb; 61 | glGenFramebuffers(1, &fb); 62 | glBindFramebuffer(GL_FRAMEBUFFER, fb.get()); 63 | glDrawBuffer(GL_COLOR_ATTACHMENT0); 64 | return fb; 65 | } 66 | 67 | gl::texture_handle water_frame_buffers::create_texture_attachment(int width, 68 | int height) 69 | { 70 | gl::texture_handle tex; 71 | glGenTextures(1, &tex); 72 | glBindTexture(GL_TEXTURE_2D, tex.get()); 73 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 74 | 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); 75 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 76 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 77 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex.get(), 0); 78 | return tex; 79 | } 80 | 81 | gl::texture_handle water_frame_buffers::create_depth_texture_attachment( 82 | int width, int height) 83 | { 84 | gl::texture_handle tex; 85 | glGenTextures(1, &tex); 86 | glBindTexture(GL_TEXTURE_2D, tex.get()); 87 | glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 88 | 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); 89 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 90 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 91 | glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tex.get(), 0); 92 | return tex; 93 | } 94 | 95 | gl::renderbuffer_handle water_frame_buffers::create_depth_buffer_attachment( 96 | int width, int height) 97 | { 98 | gl::renderbuffer_handle buf; 99 | glGenRenderbuffers(1, &buf); 100 | glBindRenderbuffer(GL_RENDERBUFFER, buf.get()); 101 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); 102 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buf.get()); 103 | return buf; 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/water_frame_buffers.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_WATER_FRAME_BUFFERS_HPP 3 | #define JAC_WATER_FRAME_BUFFERS_HPP 4 | 5 | #include "gl_handles.hpp" 6 | 7 | #include 8 | 9 | namespace jac { 10 | 11 | class water_frame_buffers { 12 | public: 13 | water_frame_buffers(); 14 | 15 | void bind_reflection_frame_buffer() const; 16 | 17 | void bind_refraction_frame_buffer() const; 18 | 19 | void unbind_current_frame_buffer() const; 20 | 21 | GLuint get_reflection_texture() const { return reflection_texture.get(); } 22 | 23 | GLuint get_refraction_texture() const { return refraction_texture.get(); } 24 | 25 | GLuint get_refraction_depth_texture() const { return refraction_depth_texture.get(); } 26 | 27 | protected: 28 | static constexpr int reflection_width = 320; 29 | static constexpr int refraction_width = 180; 30 | 31 | private: 32 | static constexpr int reflection_height = 1280; 33 | static constexpr int refraction_height = 720; 34 | 35 | void initialise_reflection_frame_buffer(); 36 | void initialise_refraction_frame_buffer(); 37 | void bind_frame_buffer(GLuint framebuffer, int width, int height) const; 38 | 39 | gl::framebuffer_handle create_frame_buffer(); 40 | gl::texture_handle create_texture_attachment(int width, int height); 41 | gl::texture_handle create_depth_texture_attachment(int width, int height); 42 | gl::renderbuffer_handle create_depth_buffer_attachment(int width, int height); 43 | 44 | gl::framebuffer_handle reflection_framebuffer; 45 | gl::texture_handle reflection_texture; 46 | gl::renderbuffer_handle reflection_depth_buffer; 47 | 48 | gl::framebuffer_handle refraction_framebuffer; 49 | gl::texture_handle refraction_texture; 50 | gl::texture_handle refraction_depth_texture; 51 | 52 | }; 53 | 54 | } 55 | 56 | #endif //JAC_WATER_FRAME_BUFFERS_HPP 57 | -------------------------------------------------------------------------------- /src/water_renderer.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "water_renderer.hpp" 3 | 4 | #include "loader.hpp" 5 | #include "maths.hpp" 6 | #include "water_frame_buffers.hpp" 7 | #include "water_tile.hpp" 8 | #include "display_manager.hpp" 9 | 10 | #include 11 | 12 | namespace jac { 13 | 14 | constexpr const char dudv_map_src[] = "waterDUDV"; 15 | constexpr const char normal_map_src[] = "normal"; 16 | constexpr auto wave_speed = 0.03f; 17 | 18 | water_renderer::water_renderer(jac::loader& loader, water_shader shader_, 19 | const glm::mat4& projection_matrix, 20 | const water_frame_buffers& fbos) 21 | : shader{std::move(shader_)}, 22 | fbos{fbos}, 23 | dudv_texture{loader.load_texture(dudv_map_src)}, 24 | normal_texture{loader.load_texture(normal_map_src)} 25 | { 26 | shader.start(); 27 | shader.connect_texture_units(); 28 | shader.load_projection_matrix(projection_matrix); 29 | shader.stop(); 30 | set_up_vao(loader); 31 | } 32 | 33 | void water_renderer::render(const std::vector& water, 34 | const jac::camera& camera, 35 | const light& sun) 36 | { 37 | prepare_render(camera, sun); 38 | for (const auto& tile : water) { 39 | auto model_matrix = maths::create_transformation_matrix( 40 | {tile.x, tile.height, tile.z}, 0, 0, 0, water_tile::tile_size); 41 | shader.load_model_matrix(model_matrix); 42 | glDrawArrays(GL_TRIANGLES, 0, quad.vertex_count); 43 | } 44 | unbind(); 45 | } 46 | 47 | void water_renderer::prepare_render(const jac::camera& camera, const jac::light& sun) 48 | { 49 | shader.start(); 50 | shader.load_view_matrix(camera); 51 | move_factor += wave_speed * get_frame_time_seconds().count(); 52 | move_factor = std::fmod(move_factor, 1); 53 | shader.load_move_factor(move_factor); 54 | shader.load_light(sun); 55 | glBindVertexArray(quad.vao_id); 56 | glEnableVertexAttribArray(0); 57 | glActiveTexture(GL_TEXTURE0); 58 | glBindTexture(GL_TEXTURE_2D, fbos.get_reflection_texture()); 59 | glActiveTexture(GL_TEXTURE1); 60 | glBindTexture(GL_TEXTURE_2D, fbos.get_refraction_texture()); 61 | glActiveTexture(GL_TEXTURE2); 62 | glBindTexture(GL_TEXTURE_2D, dudv_texture); 63 | glActiveTexture(GL_TEXTURE3); 64 | glBindTexture(GL_TEXTURE_2D, normal_texture); 65 | glActiveTexture(GL_TEXTURE4); 66 | glBindTexture(GL_TEXTURE_2D, fbos.get_refraction_depth_texture()); 67 | 68 | glEnable(GL_BLEND); 69 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 70 | } 71 | 72 | void water_renderer::unbind() const 73 | { 74 | glDisable(GL_BLEND); 75 | glDisableVertexAttribArray(0); 76 | glBindVertexArray(0); 77 | shader.stop(); 78 | } 79 | 80 | void water_renderer::set_up_vao(jac::loader& loader) 81 | { 82 | const std::vector vertices{ -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1 }; 83 | quad = loader.load_to_vao(vertices, 2); 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/water_renderer.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_WATER_RENDERER_HPP 3 | #define JAC_WATER_RENDERER_HPP 4 | 5 | #include "raw_model.hpp" 6 | #include "water_shader.hpp" 7 | #include "water_frame_buffers.hpp" 8 | 9 | #include 10 | 11 | namespace jac { 12 | 13 | struct light; 14 | class loader; 15 | struct water_tile; 16 | class water_frame_buffers; 17 | 18 | class water_renderer { 19 | public: 20 | water_renderer(jac::loader& loader, 21 | water_shader shader, 22 | const glm::mat4& projection_matrix, 23 | const water_frame_buffers& fbos); 24 | 25 | void render(const std::vector& water, 26 | const jac::camera& camera, 27 | const light& sun); 28 | 29 | private: 30 | void prepare_render(const jac::camera& camera, const light& sun); 31 | void unbind() const; 32 | void set_up_vao(jac::loader& loader); 33 | 34 | raw_model quad{}; 35 | water_shader shader{}; 36 | const water_frame_buffers& fbos; 37 | GLuint dudv_texture = 0; 38 | GLuint normal_texture = 0; 39 | float move_factor = 0; 40 | }; 41 | 42 | } 43 | 44 | #endif //JAC_WATER_RENDERER_HPP 45 | -------------------------------------------------------------------------------- /src/water_shader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "water_shader.hpp" 3 | 4 | #include "camera.hpp" 5 | #include "light.hpp" 6 | #include "maths.hpp" 7 | 8 | constexpr char vertex_shader_source[] = "shaders/water_vertex_shader.vert"; 9 | constexpr char fragment_shader_source[] = "shaders/water_fragment_shader.frag"; 10 | 11 | 12 | namespace jac { 13 | 14 | water_shader::water_shader() 15 | : shader_program(vertex_shader_source, fragment_shader_source) 16 | { 17 | link(); 18 | } 19 | 20 | void water_shader::load_projection_matrix(const glm::mat4& matrix) const 21 | { 22 | load_matrix(location_projection_matrix, matrix); 23 | } 24 | 25 | void water_shader::load_view_matrix(const jac::camera& camera) const 26 | { 27 | auto matrix = maths::create_view_matrix(camera); 28 | load_matrix(location_view_matrix, matrix); 29 | load_vector(location_camera_position, camera.get_position()); 30 | } 31 | 32 | void water_shader::load_model_matrix(const glm::mat4& matrix) const 33 | { 34 | load_matrix(location_model_matrix, matrix); 35 | } 36 | 37 | void water_shader::bind_attributes() 38 | { 39 | bind_attribute(0, "position"); 40 | } 41 | 42 | void water_shader::get_all_uniform_locations() 43 | { 44 | location_projection_matrix = get_uniform_location("projectionMatrix"); 45 | location_view_matrix = get_uniform_location("viewMatrix"); 46 | location_model_matrix = get_uniform_location("modelMatrix"); 47 | location_reflection_texture = get_uniform_location("reflectionTexture"); 48 | location_refraction_texture = get_uniform_location("refractionTexture"); 49 | location_dudv_map = get_uniform_location("dudvMap"); 50 | location_move_factor = get_uniform_location("moveFactor"); 51 | location_camera_position = get_uniform_location("cameraPosition"); 52 | location_normal_map = get_uniform_location("normalMap"); 53 | location_light_position = get_uniform_location("lightPosition"); 54 | location_light_colour = get_uniform_location("lightColour"); 55 | location_depth_map = get_uniform_location("depthMap"); 56 | } 57 | 58 | void water_shader::connect_texture_units() const 59 | { 60 | load_int(location_reflection_texture, 0); 61 | load_int(location_refraction_texture, 1); 62 | load_int(location_dudv_map, 2); 63 | load_int(location_normal_map, 3); 64 | load_int(location_depth_map, 4); 65 | } 66 | 67 | void water_shader::load_move_factor(float factor) const 68 | { 69 | load_float(location_move_factor, factor); 70 | } 71 | 72 | void water_shader::load_light(const light& sun) const 73 | { 74 | load_vector(location_light_position, sun.position); 75 | load_vector(location_light_colour, sun.colour); 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/water_shader.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef JAC_WATER_SHADER_HPP 3 | #define JAC_WATER_SHADER_HPP 4 | 5 | #include "shader_program.hpp" 6 | 7 | namespace jac { 8 | 9 | class camera; 10 | struct light; 11 | 12 | class water_shader final : public shader_program { 13 | public: 14 | water_shader(); 15 | 16 | void load_projection_matrix(const glm::mat4& matrix) const; 17 | void load_view_matrix(const jac::camera& camera) const; 18 | void load_model_matrix(const glm::mat4& matrix) const; 19 | void load_move_factor(float factor) const; 20 | void load_light(const jac::light& light) const; 21 | void connect_texture_units() const; 22 | 23 | private: 24 | virtual void bind_attributes() override; 25 | virtual void get_all_uniform_locations() override; 26 | 27 | int location_model_matrix = 0; 28 | int location_view_matrix = 0; 29 | int location_projection_matrix = 0; 30 | int location_reflection_texture = 0; 31 | int location_refraction_texture = 0; 32 | int location_dudv_map = 0; 33 | int location_move_factor = 0; 34 | int location_camera_position = 0; 35 | int location_normal_map = 0; 36 | int location_light_colour = 0; 37 | int location_light_position = 0; 38 | int location_depth_map = 0; 39 | }; 40 | 41 | } 42 | 43 | #endif //JAC_WATER_SHADER_HPP 44 | -------------------------------------------------------------------------------- /src/water_tile.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "water_tile.hpp" 3 | -------------------------------------------------------------------------------- /src/water_tile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JAC_WATER_TILE_HPP 2 | #define JAC_WATER_TILE_HPP 3 | 4 | namespace jac { 5 | 6 | struct water_tile { 7 | float x = 0; 8 | float z = 0; 9 | float height = 0; 10 | 11 | static constexpr float tile_size = 60.0f; 12 | }; 13 | 14 | } 15 | 16 | #endif //JAC_WATER_TILE_HPP 17 | --------------------------------------------------------------------------------