├── .gitattributes ├── README.md ├── bin └── vs2022 │ └── x64 │ ├── Debug │ └── msvcr120.dll │ └── Release │ └── msvcr120.dll ├── build ├── build_x64.bat ├── build_x86.bat ├── generate_vs2022.bat ├── premake5.exe └── premake5.lua ├── clean.bat ├── external └── lpng1615 │ ├── include │ ├── png.h │ ├── pngconf.h │ └── pnglibconf.h │ └── lib │ ├── x64 │ ├── libpng16.dll │ └── libpng16.lib │ └── x86 │ ├── libpng16.dll │ └── libpng16.lib ├── res ├── cloud │ └── cloud.png ├── font │ └── font.png ├── shaders │ ├── binary │ │ ├── cloud.frag.bin │ │ ├── cloud.vert.bin │ │ ├── skydome.frag.bin │ │ ├── skydome.vert.bin │ │ ├── solid.frag.bin │ │ ├── solid.vert.bin │ │ ├── text.frag.bin │ │ ├── text.vert.bin │ │ ├── wireframe.frag.bin │ │ └── wireframe.vert.bin │ ├── cloud.frag │ ├── cloud.vert │ ├── compile.bat │ ├── fxc.exe │ ├── skydome.frag │ ├── skydome.vert │ ├── solid.frag │ ├── solid.vert │ ├── text.frag │ ├── text.vert │ ├── wireframe.frag │ └── wireframe.vert └── terrain │ ├── detail.png │ ├── gcanyon_color_4k2k.png │ ├── gcanyon_height_4k2k.png │ ├── ps_height_4k.png │ └── ps_texture_4k.png └── source ├── DXApp.cpp ├── DXApp.h ├── Demo.cpp ├── Demo.h ├── GeoMipMapping.cpp ├── GeoMipMapping.h ├── Main.cpp ├── Precompiled.cpp ├── Precompiled.h ├── Renderer ├── ConstantBuffers.cpp ├── ConstantBuffers.h ├── RenderCloud.cpp ├── RenderCloud.h ├── RenderShared.cpp ├── RenderShared.h ├── RenderSkydome.cpp ├── RenderSkydome.h ├── RenderTerrain.cpp ├── RenderTerrain.h ├── RenderText.cpp ├── RenderText.h ├── Renderer.cpp ├── Renderer.h ├── Shaders.cpp ├── Shaders.h ├── States.cpp └── States.h ├── Shared.cpp ├── Shared.h ├── Terrain.cpp ├── Terrain.h ├── Viewer.cpp └── Viewer.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GeoMipMapping 2 | 3 | This demo implemented old GeoMipMapping terrain LOD algorithm. 4 | It is base on the paper Fast Terrain Rendering Using Geometrical MipMapping which 5 | published by Willem H. de Boer in 2000. 6 | 7 | This demo include 2 test scenes: 4097 * 2049 Grand Canyan and 4097 * 4097 Puget Sound. 8 | -------------------------------------------------------------------------------- /bin/vs2022/x64/Debug/msvcr120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/bin/vs2022/x64/Debug/msvcr120.dll -------------------------------------------------------------------------------- /bin/vs2022/x64/Release/msvcr120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/bin/vs2022/x64/Release/msvcr120.dll -------------------------------------------------------------------------------- /build/build_x64.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set /p vs="select a build target (1: vs2013, 2: vs2015): " 3 | if %vs% == 1 ( 4 | premake5 vs2013 5 | "%VS120COMNTOOLS%..\IDE\devenv.com" vs2013\GeoMipMapping.sln /build "Release|x64" 6 | ) 7 | if %vs% == 2 ( 8 | premake5 vs2015 9 | "%VS140COMNTOOLS%..\IDE\devenv.com" vs2015\GeoMipMapping.sln /build "Release|x64" 10 | ) 11 | pause -------------------------------------------------------------------------------- /build/build_x86.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set /p vs="select a build target (1: vs2013, 2: vs2015): " 3 | if %vs% == 1 ( 4 | premake5 vs2013 5 | "%VS120COMNTOOLS%..\IDE\devenv.com" vs2013\GeoMipMapping.sln /build "Release|Win32" 6 | ) 7 | if %vs% == 2 ( 8 | premake5 vs2015 9 | "%VS140COMNTOOLS%..\IDE\devenv.com" vs2015\GeoMipMapping.sln /build "Release|Win32" 10 | ) 11 | pause -------------------------------------------------------------------------------- /build/generate_vs2022.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | premake5 vs2022 3 | pause -------------------------------------------------------------------------------- /build/premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/build/premake5.exe -------------------------------------------------------------------------------- /build/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "GeoMipMapping" 2 | configurations { "Debug", "Release" } 3 | platforms { "Win32", "x64" } 4 | location "%{_ACTION}" 5 | 6 | filter { "platforms:Win32" } 7 | system "Windows" 8 | architecture "x86" 9 | 10 | filter { "platforms:x64" } 11 | system "Windows" 12 | architecture "x86_64" 13 | 14 | filter "configurations:Debug" 15 | defines { "_DEBUG" } 16 | symbols "On" 17 | 18 | filter "configurations:Release" 19 | defines { "NDEBUG" } 20 | symbols "On" 21 | optimize "Speed" 22 | filter {} -- close filter scope 23 | 24 | project "GeoMipMapping" 25 | location "../build/%{_ACTION}/projects" -- put '../build/' prefix or 'includedirs' will generate absolute path 26 | kind "ConsoleApp" 27 | language "C++" 28 | targetdir "../bin/%{_ACTION}/%{cfg.platform}/%{cfg.buildcfg}" 29 | objdir "../intermediate/%{_ACTION}/%{cfg.platform}/%{cfg.buildcfg}/GeoMipMapping" 30 | links { "d3d11.lib", "libpng16.lib" } 31 | 32 | defines { 33 | "WIN32", 34 | "_CONSOLE" 35 | } 36 | 37 | files { 38 | "../source/**.h", 39 | "../source/**.cpp" 40 | } 41 | 42 | pchheader "Precompiled.h" 43 | pchsource "../source/Precompiled.cpp" 44 | 45 | includedirs { 46 | "../external/lpng1615/include", 47 | "../source" 48 | } 49 | 50 | filter "platforms:Win32" 51 | libdirs { 52 | "../external/lpng1615/lib/x86" 53 | } 54 | 55 | -- the path must using backslash and the path is relative to project's directory 56 | postbuildcommands { "if not exist ..\\..\\..\\bin\\%{_ACTION}\\%{cfg.platform}\\%{cfg.buildcfg}\\libpng16.dll ( \ 57 | copy ..\\..\\..\\external\\lpng1615\\lib\\x86\\libpng16.dll ..\\..\\..\\bin\\%{_ACTION}\\%{cfg.platform}\\%{cfg.buildcfg})" 58 | } 59 | 60 | filter "platforms:x64" 61 | libdirs { 62 | "../external/lpng1615/lib/x64" 63 | } 64 | postbuildcommands { "if not exist ..\\..\\..\\bin\\%{_ACTION}\\%{cfg.platform}\\%{cfg.buildcfg}\\libpng16.dll ( \ 65 | copy ..\\..\\..\\external\\lpng1615\\lib\\x64\\libpng16.dll ..\\..\\..\\bin\\%{_ACTION}\\%{cfg.platform}\\%{cfg.buildcfg})" 66 | } 67 | 68 | filter "files:../source/DXApp.cpp" 69 | flags { "NoPCH" } 70 | 71 | filter {} 72 | 73 | -------------------------------------------------------------------------------- /clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rmdir /s /q intermediate 3 | 4 | 5 | cd build 6 | rmdir /s /q vs2013\ipch 7 | rmdir /s /q vs2015\ipch 8 | rmdir /s /q vs2017\ipch 9 | for /r /d %%i in (*) do del "%%i\*.sdf" 10 | for /r /d %%i in (*) do del /A:h "%%i\*.suo" 11 | for /r /d %%i in (*) do del "%%i\*.VC.db" 12 | for /r /d %%i in (*) do del "%%i\*.user" 13 | for /r /d %%i in (*) do del "%%i\*.aps" 14 | cd .. 15 | 16 | cd bin 17 | for /r /d %%i in (*) do del "%%i\*.ilk" 18 | for /r /d %%i in (*) do del "%%i\*.pdb" 19 | for /r /d %%i in (*) do del "%%i\*.exp" 20 | for /r /d %%i in (*) do del "%%i\*.iobj" 21 | for /r /d %%i in (*) do del "%%i\*.ipdb" 22 | for /r /d %%i in (*) do del "%%i\*.log" 23 | cd .. 24 | 25 | pause 26 | -------------------------------------------------------------------------------- /external/lpng1615/include/pngconf.h: -------------------------------------------------------------------------------- 1 | 2 | /* pngconf.h - machine configurable file for libpng 3 | * 4 | * libpng version 1.6.15,November 20, 2014 5 | * 6 | * Copyright (c) 1998-2014 Glenn Randers-Pehrson 7 | * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 8 | * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 9 | * 10 | * This code is released under the libpng license. 11 | * For conditions of distribution and use, see the disclaimer 12 | * and license in png.h 13 | * 14 | */ 15 | 16 | /* Any machine specific code is near the front of this file, so if you 17 | * are configuring libpng for a machine, you may want to read the section 18 | * starting here down to where it starts to typedef png_color, png_text, 19 | * and png_info. 20 | */ 21 | 22 | #ifndef PNGCONF_H 23 | #define PNGCONF_H 24 | 25 | /* To do: Do all of this in scripts/pnglibconf.dfa */ 26 | #ifdef PNG_SAFE_LIMITS_SUPPORTED 27 | # ifdef PNG_USER_WIDTH_MAX 28 | # undef PNG_USER_WIDTH_MAX 29 | # define PNG_USER_WIDTH_MAX 1000000L 30 | # endif 31 | # ifdef PNG_USER_HEIGHT_MAX 32 | # undef PNG_USER_HEIGHT_MAX 33 | # define PNG_USER_HEIGHT_MAX 1000000L 34 | # endif 35 | # ifdef PNG_USER_CHUNK_MALLOC_MAX 36 | # undef PNG_USER_CHUNK_MALLOC_MAX 37 | # define PNG_USER_CHUNK_MALLOC_MAX 4000000L 38 | # endif 39 | # ifdef PNG_USER_CHUNK_CACHE_MAX 40 | # undef PNG_USER_CHUNK_CACHE_MAX 41 | # define PNG_USER_CHUNK_CACHE_MAX 128 42 | # endif 43 | #endif 44 | 45 | #ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ 46 | 47 | /* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C 48 | * compiler for correct compilation. The following header files are required by 49 | * the standard. If your compiler doesn't provide these header files, or they 50 | * do not match the standard, you will need to provide/improve them. 51 | */ 52 | #include 53 | #include 54 | 55 | /* Library header files. These header files are all defined by ISOC90; libpng 56 | * expects conformant implementations, however, an ISOC90 conformant system need 57 | * not provide these header files if the functionality cannot be implemented. 58 | * In this case it will be necessary to disable the relevant parts of libpng in 59 | * the build of pnglibconf.h. 60 | * 61 | * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not 62 | * include this unnecessary header file. 63 | */ 64 | 65 | #ifdef PNG_STDIO_SUPPORTED 66 | /* Required for the definition of FILE: */ 67 | # include 68 | #endif 69 | 70 | #ifdef PNG_SETJMP_SUPPORTED 71 | /* Required for the definition of jmp_buf and the declaration of longjmp: */ 72 | # include 73 | #endif 74 | 75 | #ifdef PNG_CONVERT_tIME_SUPPORTED 76 | /* Required for struct tm: */ 77 | # include 78 | #endif 79 | 80 | #endif /* PNG_BUILDING_SYMBOL_TABLE */ 81 | 82 | /* Prior to 1.6.0 it was possible to turn off 'const' in declarations using 83 | * PNG_NO_CONST; this is no longer supported except for data declarations which 84 | * apparently still cause problems in 2011 on some compilers. 85 | */ 86 | #define PNG_CONST const /* backward compatibility only */ 87 | 88 | /* This controls optimization of the reading of 16 and 32 bit values 89 | * from PNG files. It can be set on a per-app-file basis - it 90 | * just changes whether a macro is used when the function is called. 91 | * The library builder sets the default; if read functions are not 92 | * built into the library the macro implementation is forced on. 93 | */ 94 | #ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED 95 | # define PNG_USE_READ_MACROS 96 | #endif 97 | #if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) 98 | # if PNG_DEFAULT_READ_MACROS 99 | # define PNG_USE_READ_MACROS 100 | # endif 101 | #endif 102 | 103 | /* COMPILER SPECIFIC OPTIONS. 104 | * 105 | * These options are provided so that a variety of difficult compilers 106 | * can be used. Some are fixed at build time (e.g. PNG_API_RULE 107 | * below) but still have compiler specific implementations, others 108 | * may be changed on a per-file basis when compiling against libpng. 109 | */ 110 | 111 | /* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect 112 | * against legacy (pre ISOC90) compilers that did not understand function 113 | * prototypes. It is not required for modern C compilers. 114 | */ 115 | #ifndef PNGARG 116 | # define PNGARG(arglist) arglist 117 | #endif 118 | 119 | /* Function calling conventions. 120 | * ============================= 121 | * Normally it is not necessary to specify to the compiler how to call 122 | * a function - it just does it - however on x86 systems derived from 123 | * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems 124 | * and some others) there are multiple ways to call a function and the 125 | * default can be changed on the compiler command line. For this reason 126 | * libpng specifies the calling convention of every exported function and 127 | * every function called via a user supplied function pointer. This is 128 | * done in this file by defining the following macros: 129 | * 130 | * PNGAPI Calling convention for exported functions. 131 | * PNGCBAPI Calling convention for user provided (callback) functions. 132 | * PNGCAPI Calling convention used by the ANSI-C library (required 133 | * for longjmp callbacks and sometimes used internally to 134 | * specify the calling convention for zlib). 135 | * 136 | * These macros should never be overridden. If it is necessary to 137 | * change calling convention in a private build this can be done 138 | * by setting PNG_API_RULE (which defaults to 0) to one of the values 139 | * below to select the correct 'API' variants. 140 | * 141 | * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. 142 | * This is correct in every known environment. 143 | * PNG_API_RULE=1 Use the operating system convention for PNGAPI and 144 | * the 'C' calling convention (from PNGCAPI) for 145 | * callbacks (PNGCBAPI). This is no longer required 146 | * in any known environment - if it has to be used 147 | * please post an explanation of the problem to the 148 | * libpng mailing list. 149 | * 150 | * These cases only differ if the operating system does not use the C 151 | * calling convention, at present this just means the above cases 152 | * (x86 DOS/Windows sytems) and, even then, this does not apply to 153 | * Cygwin running on those systems. 154 | * 155 | * Note that the value must be defined in pnglibconf.h so that what 156 | * the application uses to call the library matches the conventions 157 | * set when building the library. 158 | */ 159 | 160 | /* Symbol export 161 | * ============= 162 | * When building a shared library it is almost always necessary to tell 163 | * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' 164 | * is used to mark the symbols. On some systems these symbols can be 165 | * extracted at link time and need no special processing by the compiler, 166 | * on other systems the symbols are flagged by the compiler and just 167 | * the declaration requires a special tag applied (unfortunately) in a 168 | * compiler dependent way. Some systems can do either. 169 | * 170 | * A small number of older systems also require a symbol from a DLL to 171 | * be flagged to the program that calls it. This is a problem because 172 | * we do not know in the header file included by application code that 173 | * the symbol will come from a shared library, as opposed to a statically 174 | * linked one. For this reason the application must tell us by setting 175 | * the magic flag PNG_USE_DLL to turn on the special processing before 176 | * it includes png.h. 177 | * 178 | * Four additional macros are used to make this happen: 179 | * 180 | * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from 181 | * the build or imported if PNG_USE_DLL is set - compiler 182 | * and system specific. 183 | * 184 | * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to 185 | * 'type', compiler specific. 186 | * 187 | * PNG_DLL_EXPORT Set to the magic to use during a libpng build to 188 | * make a symbol exported from the DLL. Not used in the 189 | * public header files; see pngpriv.h for how it is used 190 | * in the libpng build. 191 | * 192 | * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come 193 | * from a DLL - used to define PNG_IMPEXP when 194 | * PNG_USE_DLL is set. 195 | */ 196 | 197 | /* System specific discovery. 198 | * ========================== 199 | * This code is used at build time to find PNG_IMPEXP, the API settings 200 | * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL 201 | * import processing is possible. On Windows systems it also sets 202 | * compiler-specific macros to the values required to change the calling 203 | * conventions of the various functions. 204 | */ 205 | #if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ 206 | defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) 207 | /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or 208 | * MinGW on any architecture currently supported by Windows. Also includes 209 | * Watcom builds but these need special treatment because they are not 210 | * compatible with GCC or Visual C because of different calling conventions. 211 | */ 212 | # if PNG_API_RULE == 2 213 | /* If this line results in an error, either because __watcall is not 214 | * understood or because of a redefine just below you cannot use *this* 215 | * build of the library with the compiler you are using. *This* build was 216 | * build using Watcom and applications must also be built using Watcom! 217 | */ 218 | # define PNGCAPI __watcall 219 | # endif 220 | 221 | # if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) 222 | # define PNGCAPI __cdecl 223 | # if PNG_API_RULE == 1 224 | /* If this line results in an error __stdcall is not understood and 225 | * PNG_API_RULE should not have been set to '1'. 226 | */ 227 | # define PNGAPI __stdcall 228 | # endif 229 | # else 230 | /* An older compiler, or one not detected (erroneously) above, 231 | * if necessary override on the command line to get the correct 232 | * variants for the compiler. 233 | */ 234 | # ifndef PNGCAPI 235 | # define PNGCAPI _cdecl 236 | # endif 237 | # if PNG_API_RULE == 1 && !defined(PNGAPI) 238 | # define PNGAPI _stdcall 239 | # endif 240 | # endif /* compiler/api */ 241 | 242 | /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ 243 | 244 | # if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) 245 | # error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" 246 | # endif 247 | 248 | # if (defined(_MSC_VER) && _MSC_VER < 800) ||\ 249 | (defined(__BORLANDC__) && __BORLANDC__ < 0x500) 250 | /* older Borland and MSC 251 | * compilers used '__export' and required this to be after 252 | * the type. 253 | */ 254 | # ifndef PNG_EXPORT_TYPE 255 | # define PNG_EXPORT_TYPE(type) type PNG_IMPEXP 256 | # endif 257 | # define PNG_DLL_EXPORT __export 258 | # else /* newer compiler */ 259 | # define PNG_DLL_EXPORT __declspec(dllexport) 260 | # ifndef PNG_DLL_IMPORT 261 | # define PNG_DLL_IMPORT __declspec(dllimport) 262 | # endif 263 | # endif /* compiler */ 264 | 265 | #else /* !Windows */ 266 | # if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) 267 | # define PNGAPI _System 268 | # else /* !Windows/x86 && !OS/2 */ 269 | /* Use the defaults, or define PNG*API on the command line (but 270 | * this will have to be done for every compile!) 271 | */ 272 | # endif /* other system, !OS/2 */ 273 | #endif /* !Windows/x86 */ 274 | 275 | /* Now do all the defaulting . */ 276 | #ifndef PNGCAPI 277 | # define PNGCAPI 278 | #endif 279 | #ifndef PNGCBAPI 280 | # define PNGCBAPI PNGCAPI 281 | #endif 282 | #ifndef PNGAPI 283 | # define PNGAPI PNGCAPI 284 | #endif 285 | 286 | /* PNG_IMPEXP may be set on the compilation system command line or (if not set) 287 | * then in an internal header file when building the library, otherwise (when 288 | * using the library) it is set here. 289 | */ 290 | #ifndef PNG_IMPEXP 291 | # if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) 292 | /* This forces use of a DLL, disallowing static linking */ 293 | # define PNG_IMPEXP PNG_DLL_IMPORT 294 | # endif 295 | 296 | # ifndef PNG_IMPEXP 297 | # define PNG_IMPEXP 298 | # endif 299 | #endif 300 | 301 | /* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat 302 | * 'attributes' as a storage class - the attributes go at the start of the 303 | * function definition, and attributes are always appended regardless of the 304 | * compiler. This considerably simplifies these macros but may cause problems 305 | * if any compilers both need function attributes and fail to handle them as 306 | * a storage class (this is unlikely.) 307 | */ 308 | #ifndef PNG_FUNCTION 309 | # define PNG_FUNCTION(type, name, args, attributes) attributes type name args 310 | #endif 311 | 312 | #ifndef PNG_EXPORT_TYPE 313 | # define PNG_EXPORT_TYPE(type) PNG_IMPEXP type 314 | #endif 315 | 316 | /* The ordinal value is only relevant when preprocessing png.h for symbol 317 | * table entries, so we discard it here. See the .dfn files in the 318 | * scripts directory. 319 | */ 320 | #ifndef PNG_EXPORTA 321 | 322 | # define PNG_EXPORTA(ordinal, type, name, args, attributes)\ 323 | PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ 324 | extern attributes) 325 | #endif 326 | 327 | /* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, 328 | * so make something non-empty to satisfy the requirement: 329 | */ 330 | #define PNG_EMPTY /*empty list*/ 331 | 332 | #define PNG_EXPORT(ordinal, type, name, args)\ 333 | PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) 334 | 335 | /* Use PNG_REMOVED to comment out a removed interface. */ 336 | #ifndef PNG_REMOVED 337 | # define PNG_REMOVED(ordinal, type, name, args, attributes) 338 | #endif 339 | 340 | #ifndef PNG_CALLBACK 341 | # define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) 342 | #endif 343 | 344 | /* Support for compiler specific function attributes. These are used 345 | * so that where compiler support is available incorrect use of API 346 | * functions in png.h will generate compiler warnings. 347 | * 348 | * Added at libpng-1.2.41. 349 | */ 350 | 351 | #ifndef PNG_NO_PEDANTIC_WARNINGS 352 | # ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED 353 | # define PNG_PEDANTIC_WARNINGS_SUPPORTED 354 | # endif 355 | #endif 356 | 357 | #ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED 358 | /* Support for compiler specific function attributes. These are used 359 | * so that where compiler support is available, incorrect use of API 360 | * functions in png.h will generate compiler warnings. Added at libpng 361 | * version 1.2.41. Disabling these removes the warnings but may also produce 362 | * less efficient code. 363 | */ 364 | # if defined(__clang__) && defined(__has_attribute) 365 | /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ 366 | # if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) 367 | # define PNG_USE_RESULT __attribute__((__warn_unused_result__)) 368 | # endif 369 | # if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) 370 | # define PNG_NORETURN __attribute__((__noreturn__)) 371 | # endif 372 | # if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) 373 | # define PNG_ALLOCATED __attribute__((__malloc__)) 374 | # endif 375 | # if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) 376 | # define PNG_DEPRECATED __attribute__((__deprecated__)) 377 | # endif 378 | # if !defined(PNG_PRIVATE) 379 | # ifdef __has_extension 380 | # if __has_extension(attribute_unavailable_with_message) 381 | # define PNG_PRIVATE __attribute__((__unavailable__(\ 382 | "This function is not exported by libpng."))) 383 | # endif 384 | # endif 385 | # endif 386 | # ifndef PNG_RESTRICT 387 | # define PNG_RESTRICT __restrict 388 | # endif 389 | 390 | # elif defined(__GNUC__) 391 | # ifndef PNG_USE_RESULT 392 | # define PNG_USE_RESULT __attribute__((__warn_unused_result__)) 393 | # endif 394 | # ifndef PNG_NORETURN 395 | # define PNG_NORETURN __attribute__((__noreturn__)) 396 | # endif 397 | # if __GNUC__ >= 3 398 | # ifndef PNG_ALLOCATED 399 | # define PNG_ALLOCATED __attribute__((__malloc__)) 400 | # endif 401 | # ifndef PNG_DEPRECATED 402 | # define PNG_DEPRECATED __attribute__((__deprecated__)) 403 | # endif 404 | # ifndef PNG_PRIVATE 405 | # if 0 /* Doesn't work so we use deprecated instead*/ 406 | # define PNG_PRIVATE \ 407 | __attribute__((warning("This function is not exported by libpng."))) 408 | # else 409 | # define PNG_PRIVATE \ 410 | __attribute__((__deprecated__)) 411 | # endif 412 | # endif 413 | # if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) 414 | # ifndef PNG_RESTRICT 415 | # define PNG_RESTRICT __restrict 416 | # endif 417 | # endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ 418 | # endif /* __GNUC__ >= 3 */ 419 | 420 | # elif defined(_MSC_VER) && (_MSC_VER >= 1300) 421 | # ifndef PNG_USE_RESULT 422 | # define PNG_USE_RESULT /* not supported */ 423 | # endif 424 | # ifndef PNG_NORETURN 425 | # define PNG_NORETURN __declspec(noreturn) 426 | # endif 427 | # ifndef PNG_ALLOCATED 428 | # if (_MSC_VER >= 1400) 429 | # define PNG_ALLOCATED __declspec(restrict) 430 | # endif 431 | # endif 432 | # ifndef PNG_DEPRECATED 433 | # define PNG_DEPRECATED __declspec(deprecated) 434 | # endif 435 | # ifndef PNG_PRIVATE 436 | # define PNG_PRIVATE __declspec(deprecated) 437 | # endif 438 | # ifndef PNG_RESTRICT 439 | # if (_MSC_VER >= 1400) 440 | # define PNG_RESTRICT __restrict 441 | # endif 442 | # endif 443 | 444 | # elif defined(__WATCOMC__) 445 | # ifndef PNG_RESTRICT 446 | # define PNG_RESTRICT __restrict 447 | # endif 448 | # endif 449 | #endif /* PNG_PEDANTIC_WARNINGS */ 450 | 451 | #ifndef PNG_DEPRECATED 452 | # define PNG_DEPRECATED /* Use of this function is deprecated */ 453 | #endif 454 | #ifndef PNG_USE_RESULT 455 | # define PNG_USE_RESULT /* The result of this function must be checked */ 456 | #endif 457 | #ifndef PNG_NORETURN 458 | # define PNG_NORETURN /* This function does not return */ 459 | #endif 460 | #ifndef PNG_ALLOCATED 461 | # define PNG_ALLOCATED /* The result of the function is new memory */ 462 | #endif 463 | #ifndef PNG_PRIVATE 464 | # define PNG_PRIVATE /* This is a private libpng function */ 465 | #endif 466 | #ifndef PNG_RESTRICT 467 | # define PNG_RESTRICT /* The C99 "restrict" feature */ 468 | #endif 469 | 470 | #ifndef PNG_FP_EXPORT /* A floating point API. */ 471 | # ifdef PNG_FLOATING_POINT_SUPPORTED 472 | # define PNG_FP_EXPORT(ordinal, type, name, args)\ 473 | PNG_EXPORT(ordinal, type, name, args); 474 | # else /* No floating point APIs */ 475 | # define PNG_FP_EXPORT(ordinal, type, name, args) 476 | # endif 477 | #endif 478 | #ifndef PNG_FIXED_EXPORT /* A fixed point API. */ 479 | # ifdef PNG_FIXED_POINT_SUPPORTED 480 | # define PNG_FIXED_EXPORT(ordinal, type, name, args)\ 481 | PNG_EXPORT(ordinal, type, name, args); 482 | # else /* No fixed point APIs */ 483 | # define PNG_FIXED_EXPORT(ordinal, type, name, args) 484 | # endif 485 | #endif 486 | 487 | #ifndef PNG_BUILDING_SYMBOL_TABLE 488 | /* Some typedefs to get us started. These should be safe on most of the common 489 | * platforms. 490 | * 491 | * png_uint_32 and png_int_32 may, currently, be larger than required to hold a 492 | * 32-bit value however this is not normally advisable. 493 | * 494 | * png_uint_16 and png_int_16 should always be two bytes in size - this is 495 | * verified at library build time. 496 | * 497 | * png_byte must always be one byte in size. 498 | * 499 | * The checks below use constants from limits.h, as defined by the ISOC90 500 | * standard. 501 | */ 502 | #if CHAR_BIT == 8 && UCHAR_MAX == 255 503 | typedef unsigned char png_byte; 504 | #else 505 | # error "libpng requires 8 bit bytes" 506 | #endif 507 | 508 | #if INT_MIN == -32768 && INT_MAX == 32767 509 | typedef int png_int_16; 510 | #elif SHRT_MIN == -32768 && SHRT_MAX == 32767 511 | typedef short png_int_16; 512 | #else 513 | # error "libpng requires a signed 16 bit type" 514 | #endif 515 | 516 | #if UINT_MAX == 65535 517 | typedef unsigned int png_uint_16; 518 | #elif USHRT_MAX == 65535 519 | typedef unsigned short png_uint_16; 520 | #else 521 | # error "libpng requires an unsigned 16 bit type" 522 | #endif 523 | 524 | #if INT_MIN < -2147483646 && INT_MAX > 2147483646 525 | typedef int png_int_32; 526 | #elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 527 | typedef long int png_int_32; 528 | #else 529 | # error "libpng requires a signed 32 bit (or more) type" 530 | #endif 531 | 532 | #if UINT_MAX > 4294967294 533 | typedef unsigned int png_uint_32; 534 | #elif ULONG_MAX > 4294967294 535 | typedef unsigned long int png_uint_32; 536 | #else 537 | # error "libpng requires an unsigned 32 bit (or more) type" 538 | #endif 539 | 540 | /* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, 541 | * requires an ISOC90 compiler and relies on consistent behavior of sizeof. 542 | */ 543 | typedef size_t png_size_t; 544 | typedef ptrdiff_t png_ptrdiff_t; 545 | 546 | /* libpng needs to know the maximum value of 'size_t' and this controls the 547 | * definition of png_alloc_size_t, below. This maximum value of size_t limits 548 | * but does not control the maximum allocations the library makes - there is 549 | * direct application control of this through png_set_user_limits(). 550 | */ 551 | #ifndef PNG_SMALL_SIZE_T 552 | /* Compiler specific tests for systems where size_t is known to be less than 553 | * 32 bits (some of these systems may no longer work because of the lack of 554 | * 'far' support; see above.) 555 | */ 556 | # if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ 557 | (defined(_MSC_VER) && defined(MAXSEG_64K)) 558 | # define PNG_SMALL_SIZE_T 559 | # endif 560 | #endif 561 | 562 | /* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no 563 | * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to 564 | * png_alloc_size_t are not necessary; in fact, it is recommended not to use 565 | * them at all so that the compiler can complain when something turns out to be 566 | * problematic. 567 | * 568 | * Casts in the other direction (from png_alloc_size_t to png_size_t or 569 | * png_uint_32) should be explicitly applied; however, we do not expect to 570 | * encounter practical situations that require such conversions. 571 | * 572 | * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than 573 | * 4294967295 - i.e. less than the maximum value of png_uint_32. 574 | */ 575 | #ifdef PNG_SMALL_SIZE_T 576 | typedef png_uint_32 png_alloc_size_t; 577 | #else 578 | typedef png_size_t png_alloc_size_t; 579 | #endif 580 | 581 | /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler 582 | * implementations of Intel CPU specific support of user-mode segmented address 583 | * spaces, where 16-bit pointers address more than 65536 bytes of memory using 584 | * separate 'segment' registers. The implementation requires two different 585 | * types of pointer (only one of which includes the segment value.) 586 | * 587 | * If required this support is available in version 1.2 of libpng and may be 588 | * available in versions through 1.5, although the correctness of the code has 589 | * not been verified recently. 590 | */ 591 | 592 | /* Typedef for floating-point numbers that are converted to fixed-point with a 593 | * multiple of 100,000, e.g., gamma 594 | */ 595 | typedef png_int_32 png_fixed_point; 596 | 597 | /* Add typedefs for pointers */ 598 | typedef void * png_voidp; 599 | typedef const void * png_const_voidp; 600 | typedef png_byte * png_bytep; 601 | typedef const png_byte * png_const_bytep; 602 | typedef png_uint_32 * png_uint_32p; 603 | typedef const png_uint_32 * png_const_uint_32p; 604 | typedef png_int_32 * png_int_32p; 605 | typedef const png_int_32 * png_const_int_32p; 606 | typedef png_uint_16 * png_uint_16p; 607 | typedef const png_uint_16 * png_const_uint_16p; 608 | typedef png_int_16 * png_int_16p; 609 | typedef const png_int_16 * png_const_int_16p; 610 | typedef char * png_charp; 611 | typedef const char * png_const_charp; 612 | typedef png_fixed_point * png_fixed_point_p; 613 | typedef const png_fixed_point * png_const_fixed_point_p; 614 | typedef png_size_t * png_size_tp; 615 | typedef const png_size_t * png_const_size_tp; 616 | 617 | #ifdef PNG_STDIO_SUPPORTED 618 | typedef FILE * png_FILE_p; 619 | #endif 620 | 621 | #ifdef PNG_FLOATING_POINT_SUPPORTED 622 | typedef double * png_doublep; 623 | typedef const double * png_const_doublep; 624 | #endif 625 | 626 | /* Pointers to pointers; i.e. arrays */ 627 | typedef png_byte * * png_bytepp; 628 | typedef png_uint_32 * * png_uint_32pp; 629 | typedef png_int_32 * * png_int_32pp; 630 | typedef png_uint_16 * * png_uint_16pp; 631 | typedef png_int_16 * * png_int_16pp; 632 | typedef const char * * png_const_charpp; 633 | typedef char * * png_charpp; 634 | typedef png_fixed_point * * png_fixed_point_pp; 635 | #ifdef PNG_FLOATING_POINT_SUPPORTED 636 | typedef double * * png_doublepp; 637 | #endif 638 | 639 | /* Pointers to pointers to pointers; i.e., pointer to array */ 640 | typedef char * * * png_charppp; 641 | 642 | #endif /* PNG_BUILDING_SYMBOL_TABLE */ 643 | 644 | #endif /* PNGCONF_H */ 645 | -------------------------------------------------------------------------------- /external/lpng1615/include/pnglibconf.h: -------------------------------------------------------------------------------- 1 | /* libpng 1.6.15 STANDARD API DEFINITION */ 2 | 3 | /* pnglibconf.h - library build configuration */ 4 | 5 | /* Libpng version 1.6.15 - November 20, 2014 */ 6 | 7 | /* Copyright (c) 1998-2014 Glenn Randers-Pehrson */ 8 | 9 | /* This code is released under the libpng license. */ 10 | /* For conditions of distribution and use, see the disclaimer */ 11 | /* and license in png.h */ 12 | 13 | /* pnglibconf.h */ 14 | /* Machine generated file: DO NOT EDIT */ 15 | /* Derived from: scripts/pnglibconf.dfa */ 16 | #ifndef PNGLCONF_H 17 | #define PNGLCONF_H 18 | /* options */ 19 | #define PNG_16BIT_SUPPORTED 20 | #define PNG_ALIGNED_MEMORY_SUPPORTED 21 | /*#undef PNG_ARM_NEON_API_SUPPORTED*/ 22 | /*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ 23 | #define PNG_BENIGN_ERRORS_SUPPORTED 24 | #define PNG_BENIGN_READ_ERRORS_SUPPORTED 25 | /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ 26 | #define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED 27 | #define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED 28 | #define PNG_COLORSPACE_SUPPORTED 29 | #define PNG_CONSOLE_IO_SUPPORTED 30 | #define PNG_CONVERT_tIME_SUPPORTED 31 | #define PNG_EASY_ACCESS_SUPPORTED 32 | /*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ 33 | #define PNG_ERROR_TEXT_SUPPORTED 34 | #define PNG_FIXED_POINT_SUPPORTED 35 | #define PNG_FLOATING_ARITHMETIC_SUPPORTED 36 | #define PNG_FLOATING_POINT_SUPPORTED 37 | #define PNG_FORMAT_AFIRST_SUPPORTED 38 | #define PNG_FORMAT_BGR_SUPPORTED 39 | #define PNG_GAMMA_SUPPORTED 40 | #define PNG_GET_PALETTE_MAX_SUPPORTED 41 | #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED 42 | #define PNG_INCH_CONVERSIONS_SUPPORTED 43 | #define PNG_INFO_IMAGE_SUPPORTED 44 | #define PNG_IO_STATE_SUPPORTED 45 | #define PNG_MNG_FEATURES_SUPPORTED 46 | #define PNG_POINTER_INDEXING_SUPPORTED 47 | #define PNG_PROGRESSIVE_READ_SUPPORTED 48 | #define PNG_READ_16BIT_SUPPORTED 49 | #define PNG_READ_ALPHA_MODE_SUPPORTED 50 | #define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED 51 | #define PNG_READ_BACKGROUND_SUPPORTED 52 | #define PNG_READ_BGR_SUPPORTED 53 | #define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED 54 | #define PNG_READ_COMPOSITE_NODIV_SUPPORTED 55 | #define PNG_READ_COMPRESSED_TEXT_SUPPORTED 56 | #define PNG_READ_EXPAND_16_SUPPORTED 57 | #define PNG_READ_EXPAND_SUPPORTED 58 | #define PNG_READ_FILLER_SUPPORTED 59 | #define PNG_READ_GAMMA_SUPPORTED 60 | #define PNG_READ_GET_PALETTE_MAX_SUPPORTED 61 | #define PNG_READ_GRAY_TO_RGB_SUPPORTED 62 | #define PNG_READ_INTERLACING_SUPPORTED 63 | #define PNG_READ_INT_FUNCTIONS_SUPPORTED 64 | #define PNG_READ_INVERT_ALPHA_SUPPORTED 65 | #define PNG_READ_INVERT_SUPPORTED 66 | #define PNG_READ_OPT_PLTE_SUPPORTED 67 | #define PNG_READ_PACKSWAP_SUPPORTED 68 | #define PNG_READ_PACK_SUPPORTED 69 | #define PNG_READ_QUANTIZE_SUPPORTED 70 | #define PNG_READ_RGB_TO_GRAY_SUPPORTED 71 | #define PNG_READ_SCALE_16_TO_8_SUPPORTED 72 | #define PNG_READ_SHIFT_SUPPORTED 73 | #define PNG_READ_STRIP_16_TO_8_SUPPORTED 74 | #define PNG_READ_STRIP_ALPHA_SUPPORTED 75 | #define PNG_READ_SUPPORTED 76 | #define PNG_READ_SWAP_ALPHA_SUPPORTED 77 | #define PNG_READ_SWAP_SUPPORTED 78 | #define PNG_READ_TEXT_SUPPORTED 79 | #define PNG_READ_TRANSFORMS_SUPPORTED 80 | #define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 81 | #define PNG_READ_USER_CHUNKS_SUPPORTED 82 | #define PNG_READ_USER_TRANSFORM_SUPPORTED 83 | #define PNG_READ_bKGD_SUPPORTED 84 | #define PNG_READ_cHRM_SUPPORTED 85 | #define PNG_READ_gAMA_SUPPORTED 86 | #define PNG_READ_hIST_SUPPORTED 87 | #define PNG_READ_iCCP_SUPPORTED 88 | #define PNG_READ_iTXt_SUPPORTED 89 | #define PNG_READ_oFFs_SUPPORTED 90 | #define PNG_READ_pCAL_SUPPORTED 91 | #define PNG_READ_pHYs_SUPPORTED 92 | #define PNG_READ_sBIT_SUPPORTED 93 | #define PNG_READ_sCAL_SUPPORTED 94 | #define PNG_READ_sPLT_SUPPORTED 95 | #define PNG_READ_sRGB_SUPPORTED 96 | #define PNG_READ_tEXt_SUPPORTED 97 | #define PNG_READ_tIME_SUPPORTED 98 | #define PNG_READ_tRNS_SUPPORTED 99 | #define PNG_READ_zTXt_SUPPORTED 100 | /*#undef PNG_SAFE_LIMITS_SUPPORTED*/ 101 | #define PNG_SAVE_INT_32_SUPPORTED 102 | #define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED 103 | #define PNG_SEQUENTIAL_READ_SUPPORTED 104 | #define PNG_SETJMP_SUPPORTED 105 | #define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED 106 | #define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED 107 | #define PNG_SET_OPTION_SUPPORTED 108 | #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 109 | #define PNG_SET_USER_LIMITS_SUPPORTED 110 | #define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED 111 | #define PNG_SIMPLIFIED_READ_BGR_SUPPORTED 112 | #define PNG_SIMPLIFIED_READ_SUPPORTED 113 | #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 114 | #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED 115 | #define PNG_SIMPLIFIED_WRITE_SUPPORTED 116 | #define PNG_STDIO_SUPPORTED 117 | #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED 118 | #define PNG_TEXT_SUPPORTED 119 | #define PNG_TIME_RFC1123_SUPPORTED 120 | #define PNG_UNKNOWN_CHUNKS_SUPPORTED 121 | #define PNG_USER_CHUNKS_SUPPORTED 122 | #define PNG_USER_LIMITS_SUPPORTED 123 | #define PNG_USER_MEM_SUPPORTED 124 | #define PNG_USER_TRANSFORM_INFO_SUPPORTED 125 | #define PNG_USER_TRANSFORM_PTR_SUPPORTED 126 | #define PNG_WARNINGS_SUPPORTED 127 | #define PNG_WRITE_16BIT_SUPPORTED 128 | #define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED 129 | #define PNG_WRITE_BGR_SUPPORTED 130 | #define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 131 | #define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 132 | #define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 133 | #define PNG_WRITE_FILLER_SUPPORTED 134 | #define PNG_WRITE_FILTER_SUPPORTED 135 | #define PNG_WRITE_FLUSH_SUPPORTED 136 | #define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED 137 | #define PNG_WRITE_INTERLACING_SUPPORTED 138 | #define PNG_WRITE_INT_FUNCTIONS_SUPPORTED 139 | #define PNG_WRITE_INVERT_ALPHA_SUPPORTED 140 | #define PNG_WRITE_INVERT_SUPPORTED 141 | #define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 142 | #define PNG_WRITE_PACKSWAP_SUPPORTED 143 | #define PNG_WRITE_PACK_SUPPORTED 144 | #define PNG_WRITE_SHIFT_SUPPORTED 145 | #define PNG_WRITE_SUPPORTED 146 | #define PNG_WRITE_SWAP_ALPHA_SUPPORTED 147 | #define PNG_WRITE_SWAP_SUPPORTED 148 | #define PNG_WRITE_TEXT_SUPPORTED 149 | #define PNG_WRITE_TRANSFORMS_SUPPORTED 150 | #define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 151 | #define PNG_WRITE_USER_TRANSFORM_SUPPORTED 152 | #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 153 | #define PNG_WRITE_bKGD_SUPPORTED 154 | #define PNG_WRITE_cHRM_SUPPORTED 155 | #define PNG_WRITE_gAMA_SUPPORTED 156 | #define PNG_WRITE_hIST_SUPPORTED 157 | #define PNG_WRITE_iCCP_SUPPORTED 158 | #define PNG_WRITE_iTXt_SUPPORTED 159 | #define PNG_WRITE_oFFs_SUPPORTED 160 | #define PNG_WRITE_pCAL_SUPPORTED 161 | #define PNG_WRITE_pHYs_SUPPORTED 162 | #define PNG_WRITE_sBIT_SUPPORTED 163 | #define PNG_WRITE_sCAL_SUPPORTED 164 | #define PNG_WRITE_sPLT_SUPPORTED 165 | #define PNG_WRITE_sRGB_SUPPORTED 166 | #define PNG_WRITE_tEXt_SUPPORTED 167 | #define PNG_WRITE_tIME_SUPPORTED 168 | #define PNG_WRITE_tRNS_SUPPORTED 169 | #define PNG_WRITE_zTXt_SUPPORTED 170 | #define PNG_bKGD_SUPPORTED 171 | #define PNG_cHRM_SUPPORTED 172 | #define PNG_gAMA_SUPPORTED 173 | #define PNG_hIST_SUPPORTED 174 | #define PNG_iCCP_SUPPORTED 175 | #define PNG_iTXt_SUPPORTED 176 | #define PNG_oFFs_SUPPORTED 177 | #define PNG_pCAL_SUPPORTED 178 | #define PNG_pHYs_SUPPORTED 179 | #define PNG_sBIT_SUPPORTED 180 | #define PNG_sCAL_SUPPORTED 181 | #define PNG_sPLT_SUPPORTED 182 | #define PNG_sRGB_SUPPORTED 183 | #define PNG_tEXt_SUPPORTED 184 | #define PNG_tIME_SUPPORTED 185 | #define PNG_tRNS_SUPPORTED 186 | #define PNG_zTXt_SUPPORTED 187 | /* end of options */ 188 | /* settings */ 189 | #define PNG_API_RULE 0 190 | #define PNG_COST_SHIFT 3 191 | #define PNG_DEFAULT_READ_MACROS 1 192 | #define PNG_GAMMA_THRESHOLD_FIXED 5000 193 | #define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE 194 | #define PNG_INFLATE_BUF_SIZE 1024 195 | #define PNG_MAX_GAMMA_8 11 196 | #define PNG_QUANTIZE_BLUE_BITS 5 197 | #define PNG_QUANTIZE_GREEN_BITS 5 198 | #define PNG_QUANTIZE_RED_BITS 5 199 | #define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) 200 | #define PNG_TEXT_Z_DEFAULT_STRATEGY 0 201 | #define PNG_WEIGHT_SHIFT 8 202 | #define PNG_ZBUF_SIZE 8192 203 | #define PNG_ZLIB_VERNUM 0 /* unknown */ 204 | #define PNG_Z_DEFAULT_COMPRESSION (-1) 205 | #define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 206 | #define PNG_Z_DEFAULT_STRATEGY 1 207 | #define PNG_sCAL_PRECISION 5 208 | #define PNG_sRGB_PROFILE_CHECKS 2 209 | /* end of settings */ 210 | #endif /* PNGLCONF_H */ 211 | -------------------------------------------------------------------------------- /external/lpng1615/lib/x64/libpng16.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/external/lpng1615/lib/x64/libpng16.dll -------------------------------------------------------------------------------- /external/lpng1615/lib/x64/libpng16.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/external/lpng1615/lib/x64/libpng16.lib -------------------------------------------------------------------------------- /external/lpng1615/lib/x86/libpng16.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/external/lpng1615/lib/x86/libpng16.dll -------------------------------------------------------------------------------- /external/lpng1615/lib/x86/libpng16.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/external/lpng1615/lib/x86/libpng16.lib -------------------------------------------------------------------------------- /res/cloud/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/cloud/cloud.png -------------------------------------------------------------------------------- /res/font/font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/font/font.png -------------------------------------------------------------------------------- /res/shaders/binary/cloud.frag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/cloud.frag.bin -------------------------------------------------------------------------------- /res/shaders/binary/cloud.vert.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/cloud.vert.bin -------------------------------------------------------------------------------- /res/shaders/binary/skydome.frag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/skydome.frag.bin -------------------------------------------------------------------------------- /res/shaders/binary/skydome.vert.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/skydome.vert.bin -------------------------------------------------------------------------------- /res/shaders/binary/solid.frag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/solid.frag.bin -------------------------------------------------------------------------------- /res/shaders/binary/solid.vert.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/solid.vert.bin -------------------------------------------------------------------------------- /res/shaders/binary/text.frag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/text.frag.bin -------------------------------------------------------------------------------- /res/shaders/binary/text.vert.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/text.vert.bin -------------------------------------------------------------------------------- /res/shaders/binary/wireframe.frag.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/wireframe.frag.bin -------------------------------------------------------------------------------- /res/shaders/binary/wireframe.vert.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/binary/wireframe.vert.bin -------------------------------------------------------------------------------- /res/shaders/cloud.frag: -------------------------------------------------------------------------------- 1 | cbuffer cbMove : register (b0) 2 | { 3 | float2 g_move; 4 | float2 g_move_pad; 5 | }; 6 | 7 | Texture2D g_tex : register(t0); 8 | SamplerState g_sampler : register(s0); 9 | 10 | struct VS_OUTPUT_POS_COLOR { 11 | float4 pos_homo : SV_POSITION; // position in homogeneous space 12 | float4 color : COLOR; 13 | }; 14 | 15 | float4 main(VS_OUTPUT_POS_COLOR pin) : SV_Target 16 | { 17 | float2 tex_coord = float2(pin.color.x, pin.color.y) + g_move; 18 | float4 color = g_tex.Sample(g_sampler, tex_coord); 19 | color.w = pin.color.w; 20 | return color; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /res/shaders/cloud.vert: -------------------------------------------------------------------------------- 1 | cbuffer cbWorldViewProjMatrix : register (b0) 2 | { 3 | row_major float4x4 g_WorldViewProjectionMatrix; 4 | }; 5 | 6 | struct VS_INPUT_POS_COLOR { 7 | float3 pos_local : POSITION; 8 | float4 color : COLOR; 9 | }; 10 | 11 | struct VS_OUTPUT_POS_COLOR { 12 | float4 pos_homo : SV_POSITION; // position in homogeneous space 13 | float4 color : COLOR; // pass though 14 | }; 15 | 16 | VS_OUTPUT_POS_COLOR main(VS_INPUT_POS_COLOR vin) 17 | { 18 | VS_OUTPUT_POS_COLOR vout; 19 | 20 | vout.pos_homo = mul(float4(vin.pos_local, 1.0f), g_WorldViewProjectionMatrix); 21 | vout.color = vin.color; 22 | 23 | return vout; 24 | } 25 | -------------------------------------------------------------------------------- /res/shaders/compile.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | for %%f in (*.vert) do ( fxc /T vs_5_0 /Fo binary\%%~nf.vert.bin %%~nf.vert ) 3 | for %%f in (*.frag) do ( fxc /T ps_5_0 /Fo binary\%%~nf.frag.bin %%~nf.frag ) 4 | pause -------------------------------------------------------------------------------- /res/shaders/fxc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/shaders/fxc.exe -------------------------------------------------------------------------------- /res/shaders/skydome.frag: -------------------------------------------------------------------------------- 1 | struct VS_OUTPUT_POS_COLOR { 2 | float4 pos_homo : SV_POSITION; // position in homogeneous space 3 | float4 color : COLOR; 4 | }; 5 | 6 | float4 main(VS_OUTPUT_POS_COLOR pin) : SV_Target 7 | { 8 | float4 color = pin.color; 9 | return color; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /res/shaders/skydome.vert: -------------------------------------------------------------------------------- 1 | cbuffer cbWorldViewProjMatrix : register (b0) 2 | { 3 | row_major float4x4 g_WorldViewProjectionMatrix; 4 | }; 5 | 6 | struct VS_INPUT_POS_COLOR { 7 | float3 pos_local : POSITION; 8 | float4 color : COLOR; 9 | }; 10 | 11 | struct VS_OUTPUT_POS_COLOR { 12 | float4 pos_homo : SV_POSITION; // position in homogeneous space 13 | float4 color : COLOR; // pass though 14 | }; 15 | 16 | VS_OUTPUT_POS_COLOR main(VS_INPUT_POS_COLOR vin) 17 | { 18 | VS_OUTPUT_POS_COLOR vout; 19 | 20 | vout.pos_homo = mul(float4(vin.pos_local, 1.0f), g_WorldViewProjectionMatrix); 21 | vout.color = vin.color; 22 | 23 | return vout; 24 | } 25 | -------------------------------------------------------------------------------- /res/shaders/solid.frag: -------------------------------------------------------------------------------- 1 | cbuffer cbFog : register (b0) 2 | { 3 | float4 g_fog; 4 | }; 5 | 6 | 7 | Texture2D g_tex_base : register(t0); 8 | Texture2D g_tex_detail : register(t1); 9 | SamplerState g_sampler_base : register(s0); 10 | SamplerState g_sampler_detail: register(s1); 11 | 12 | struct VS_OUTPUT_POS { 13 | float4 pos_homo : SV_POSITION; 14 | float2 tex_coord1: TEXCOORD0; 15 | float2 tex_coord2: TEXCOORD1; 16 | float3 pos_world: TEXCOORD2; 17 | }; 18 | 19 | float4 main(VS_OUTPUT_POS pin) : SV_Target 20 | { 21 | float4 fog_color = float4(g_fog.x, g_fog.y, g_fog.z, 1.0f); 22 | float fog_density = g_fog.w; 23 | float4 base_color = g_tex_base.Sample(g_sampler_base, pin.tex_coord1); 24 | float4 detail_color = g_tex_detail.Sample(g_sampler_detail, pin.tex_coord2); 25 | float4 combined_color = lerp(base_color, detail_color, 0.5f); 26 | 27 | float distance = length(pin.pos_world); 28 | float visibility = exp(-pow((distance * fog_density), 0.5f)); 29 | visibility = saturate(visibility); 30 | 31 | float a = 1.0 - visibility; 32 | 33 | float4 color = lerp(combined_color, fog_color, a); 34 | 35 | return color; 36 | } 37 | -------------------------------------------------------------------------------- /res/shaders/solid.vert: -------------------------------------------------------------------------------- 1 | cbuffer cbWorldViewMatrix : register (b0) 2 | { 3 | row_major float4x4 g_WorldViewMatrix; 4 | }; 5 | 6 | cbuffer cbWorldViewProjMatrix : register (b1) 7 | { 8 | row_major float4x4 g_WorldViewProjectionMatrix; 9 | }; 10 | 11 | cbuffer cbTexSize : register (b2) 12 | { 13 | float g_TexWidth; 14 | float g_TexHeight; 15 | float2 g_TexSizePad; 16 | 17 | }; 18 | 19 | struct VS_INPUT_POS { 20 | float3 pos_local : POSITION; 21 | }; 22 | 23 | struct VS_OUTPUT_POS { 24 | float4 pos_homo : SV_POSITION; // position in homogeneous space 25 | float2 tex_coord1: TEXCOORD0; 26 | float2 tex_coord2: TEXCOORD1; 27 | float3 pos_world: TEXCOORD2; 28 | }; 29 | 30 | VS_OUTPUT_POS main(VS_INPUT_POS vin) 31 | { 32 | VS_OUTPUT_POS vout; 33 | vout.pos_homo = mul(float4(vin.pos_local, 1.0f), g_WorldViewProjectionMatrix); 34 | vout.tex_coord1.x = vin.pos_local.x / g_TexWidth; 35 | vout.tex_coord1.y = 1.0f - vin.pos_local.y / g_TexHeight; 36 | vout.tex_coord2.x = vin.pos_local.x / 16.0f; 37 | vout.tex_coord2.y = (g_TexHeight - vin.pos_local.y) / 16.0f; 38 | float4 temp = mul(float4(vin.pos_local, 1.0f), g_WorldViewMatrix); 39 | vout.pos_world = float3(temp.x, temp.y, temp.z); 40 | return vout; 41 | } -------------------------------------------------------------------------------- /res/shaders/text.frag: -------------------------------------------------------------------------------- 1 | Texture2D g_tex : register(t0); 2 | SamplerState g_sampler : register(s0); 3 | 4 | struct VS_OUTPUT_POS_TEXCOORD { 5 | float4 pos_homo : SV_POSITION; 6 | float2 tex_coord : TEXCOORD0; 7 | }; 8 | 9 | float4 main(VS_OUTPUT_POS_TEXCOORD pin) : SV_Target 10 | { 11 | float4 tex_color = g_tex.Sample(g_sampler, pin.tex_coord); 12 | float alpha = tex_color.r; 13 | float4 color = float4(0.0f, 0.5f, 0.0f, alpha); 14 | return color; 15 | } -------------------------------------------------------------------------------- /res/shaders/text.vert: -------------------------------------------------------------------------------- 1 | cbuffer cbWorldViewProjMatrix : register (b0) 2 | { 3 | row_major float4x4 g_WorldViewProjectionMatrix; 4 | }; 5 | 6 | // vertex 7 | struct VS_INPUT_POS_TEXCOORD { 8 | float3 pos_local : POSITION; 9 | float2 tex_coord : TEXCOORD0; 10 | }; 11 | 12 | struct VS_OUTPUT_POS_TEXCOORD { 13 | float4 pos_homo : SV_POSITION; 14 | float2 tex_coord : TEXCOORD0; 15 | }; 16 | 17 | VS_OUTPUT_POS_TEXCOORD main(VS_INPUT_POS_TEXCOORD vin) 18 | { 19 | VS_OUTPUT_POS_TEXCOORD vout; 20 | 21 | vout.pos_homo = mul(float4(vin.pos_local, 1.0f), g_WorldViewProjectionMatrix); 22 | vout.tex_coord = vin.tex_coord; 23 | return vout; 24 | } 25 | -------------------------------------------------------------------------------- /res/shaders/wireframe.frag: -------------------------------------------------------------------------------- 1 | struct VS_OUTPUT_POS { 2 | float4 pos_homo : SV_POSITION; 3 | }; 4 | 5 | float4 main(VS_OUTPUT_POS pin) : SV_Target 6 | { 7 | float4 color = float4(0.3f, 0.3f, 0.3f, 1.0f); 8 | return color; 9 | } -------------------------------------------------------------------------------- /res/shaders/wireframe.vert: -------------------------------------------------------------------------------- 1 | cbuffer cbWorldViewProjMatrix : register (b0) 2 | { 3 | row_major float4x4 g_WorldViewProjectionMatrix; 4 | }; 5 | 6 | struct VS_INPUT_POS { 7 | float3 pos_local : POSITION; 8 | }; 9 | 10 | struct VS_OUTPUT_POS { 11 | float4 pos_homo : SV_POSITION; // position in homogeneous space 12 | }; 13 | 14 | VS_OUTPUT_POS main(VS_INPUT_POS vin) 15 | { 16 | VS_OUTPUT_POS vout; 17 | vout.pos_homo = mul(float4(vin.pos_local, 1.0f), g_WorldViewProjectionMatrix); 18 | return vout; 19 | } -------------------------------------------------------------------------------- /res/terrain/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/terrain/detail.png -------------------------------------------------------------------------------- /res/terrain/gcanyon_color_4k2k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/terrain/gcanyon_color_4k2k.png -------------------------------------------------------------------------------- /res/terrain/gcanyon_height_4k2k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/terrain/gcanyon_height_4k2k.png -------------------------------------------------------------------------------- /res/terrain/ps_height_4k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/terrain/ps_height_4k.png -------------------------------------------------------------------------------- /res/terrain/ps_texture_4k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjcminus/GeoMipMapping/dbd4a7a709c4a237dd89d0f8609ba0ee11691e02/res/terrain/ps_texture_4k.png -------------------------------------------------------------------------------- /source/DXApp.cpp: -------------------------------------------------------------------------------- 1 | // DXApp.cpp 2 | 3 | #include "DXApp.h" 4 | #include 5 | 6 | #pragma comment(lib, "winmm.lib") 7 | 8 | /* 9 | ================================================================================ 10 | function pointers 11 | ================================================================================ 12 | */ 13 | 14 | static reshape_func_t gReshapeFunc; 15 | static mouse_func_t gMouseFunc; 16 | static motion_func_t gMotionFunc; 17 | static keyboard_func_t gKeyboardFunc; 18 | static keyboard_func_t gKeyboardUpFunc; 19 | static void_func_t gDisplayFunc; 20 | static idle_func_t gIdleFunc; 21 | static void_func_t gCloseFunc; 22 | static d3d11_ctx_s gCtx; 23 | static RECT gClientRect; 24 | 25 | static void OnLButtonDown(int x, int y) { 26 | if (gMouseFunc) { 27 | gMouseFunc(DX_LEFT_BUTTON, DX_DOWN, x, y); 28 | } 29 | } 30 | 31 | static void OnLButtonUp(int x, int y) { 32 | if (gMouseFunc) { 33 | gMouseFunc(DX_LEFT_BUTTON, DX_UP, x, y); 34 | } 35 | } 36 | 37 | static void OnMouseMove(int x, int y) { 38 | if (gMotionFunc) { 39 | gMotionFunc(x, y); 40 | } 41 | } 42 | 43 | LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 44 | PAINTSTRUCT ps; 45 | 46 | switch (message) { 47 | case WM_LBUTTONDOWN: 48 | SetCapture(hWnd); 49 | OnLButtonDown((int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)); 50 | break; 51 | case WM_LBUTTONUP: 52 | ReleaseCapture(); 53 | OnLButtonUp((int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)); 54 | break; 55 | case WM_MOUSEMOVE: 56 | OnMouseMove((int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam)); 57 | break; 58 | case WM_KEYDOWN: 59 | case WM_SYSKEYDOWN: 60 | if (gKeyboardFunc) { 61 | gKeyboardFunc((int)wParam); 62 | } 63 | break; 64 | case WM_KEYUP: 65 | case WM_SYSKEYUP: 66 | if (gKeyboardUpFunc) { 67 | gKeyboardUpFunc((int)wParam); 68 | } 69 | break; 70 | case WM_SIZE: 71 | if (gReshapeFunc) { 72 | gReshapeFunc((int)LOWORD(lParam), (int)HIWORD(lParam)); 73 | } 74 | break; 75 | case WM_MOVE: 76 | ::GetClientRect(hWnd, &gClientRect); 77 | break; 78 | case WM_PAINT: 79 | BeginPaint(hWnd, &ps); 80 | EndPaint(hWnd, &ps); 81 | 82 | if (gDisplayFunc) { 83 | gDisplayFunc(); 84 | } 85 | break; 86 | case WM_DESTROY: 87 | PostQuitMessage(0); 88 | break; 89 | default: 90 | break; 91 | } 92 | 93 | return DefWindowProc(hWnd, message, wParam, lParam); 94 | } 95 | 96 | bool DX_CreateWindow(int width, int height, const wchar_t *title, d3d11_ctx_s **ctx) { 97 | HINSTANCE hInst = GetModuleHandle(NULL); 98 | 99 | // register demo class 100 | WNDCLASSEX wcex; 101 | 102 | wcex.cbSize = sizeof(WNDCLASSEX); 103 | 104 | // set up RegisterClass struct 105 | wcex.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 106 | wcex.lpfnWndProc = MainWndProc; 107 | wcex.cbClsExtra = 0; 108 | wcex.cbWndExtra = sizeof(LONG_PTR); 109 | wcex.hInstance = hInst; 110 | //wcex.hIcon = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON_APP)); 111 | wcex.hIcon = NULL; 112 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 113 | wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 114 | wcex.lpszMenuName = NULL; 115 | wcex.lpszClassName = L"DX"; 116 | wcex.hIconSm = NULL; // no small icon for now 117 | 118 | // register the window class 119 | RegisterClassEx(&wcex); 120 | 121 | DWORD window_style = WS_OVERLAPPEDWINDOW; 122 | DWORD ex_style = WS_EX_CLIENTEDGE; 123 | 124 | RECT wndRect; 125 | wndRect.left = 0; 126 | wndRect.top = 0; 127 | wndRect.right = width; 128 | wndRect.bottom = height; 129 | 130 | AdjustWindowRectEx(&wndRect, window_style, FALSE, ex_style); 131 | 132 | int window_cx = wndRect.right - wndRect.left; 133 | int window_cy = wndRect.bottom - wndRect.top; 134 | 135 | int screen_cx = GetSystemMetrics(SM_CXSCREEN); 136 | int screen_cy = GetSystemMetrics(SM_CYSCREEN); 137 | 138 | int pos_x = (screen_cx - window_cx) >> 1; 139 | int pos_y = (screen_cy - window_cy) >> 1; 140 | 141 | gCtx.mWnd = CreateWindowEx(ex_style, L"DX", title, window_style, pos_x, pos_y, window_cx, window_cy, nullptr, nullptr, hInst, nullptr); 142 | 143 | D3D_FEATURE_LEVEL feature_levels[] = { 144 | D3D_FEATURE_LEVEL_11_1, 145 | D3D_FEATURE_LEVEL_11_0 146 | }; 147 | 148 | D3D_FEATURE_LEVEL supported_feature_level; 149 | UINT create_flags = D3D11_CREATE_DEVICE_SINGLETHREADED; 150 | 151 | #ifdef _DEBUG 152 | create_flags |= D3D11_CREATE_DEVICE_DEBUG; 153 | #endif 154 | 155 | if (DX_FAILED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, create_flags, 156 | feature_levels, ARRAYSIZE(feature_levels), D3D11_SDK_VERSION, 157 | &gCtx.mDevice, &supported_feature_level, &gCtx.mDeviceContext))) { 158 | return false; 159 | } 160 | 161 | *ctx = &gCtx; 162 | 163 | return true; 164 | } 165 | 166 | void DX_ReshapeFunc(reshape_func_t func) { 167 | gReshapeFunc = func; 168 | } 169 | 170 | void DX_MouseFunc(mouse_func_t func) { 171 | gMouseFunc = func; 172 | } 173 | 174 | void DX_MotionFunc(motion_func_t func) { 175 | gMotionFunc = func; 176 | } 177 | 178 | void DX_KeyboardFunc(keyboard_func_t func) { 179 | gKeyboardFunc = func; 180 | } 181 | 182 | void DX_KeyboardUpFunc(keyboard_func_t func) { 183 | gKeyboardUpFunc = func; 184 | } 185 | 186 | void DX_DisplayFunc(void_func_t func) { 187 | gDisplayFunc = func; 188 | } 189 | 190 | void DX_IdleFunc(idle_func_t func) { 191 | gIdleFunc = func; 192 | } 193 | 194 | void DX_CloseFunc(void_func_t func) { 195 | gCloseFunc = func; 196 | } 197 | 198 | // utils 199 | void DX_GetClientCursorPos(POINT &pt) { 200 | ::GetCursorPos(&pt); 201 | ::ScreenToClient(gCtx.mWnd, &pt); 202 | } 203 | 204 | void DX_MoveCursorToClientCenter() { 205 | POINT pt; 206 | pt.x = (gClientRect.left + gClientRect.right) / 2; 207 | pt.y = (gClientRect.top + gClientRect.bottom) / 2; 208 | ::ClientToScreen(gCtx.mWnd, &pt); 209 | ::SetCursorPos(pt.x, pt.y); 210 | } 211 | 212 | void DX_MainLoop() { 213 | ShowWindow(gCtx.mWnd, SW_SHOW); 214 | UpdateWindow(gCtx.mWnd); 215 | 216 | ::GetClientRect(gCtx.mWnd, &gClientRect); 217 | 218 | timeBeginPeriod(1); 219 | DWORD previous = timeGetTime(); 220 | DWORD frame_ms = 1000 / DX_FPS; 221 | 222 | while (true) { 223 | MSG msg; 224 | 225 | while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 226 | if (WM_QUIT == msg.message) { 227 | goto QUIT; 228 | } 229 | TranslateMessage(&msg); 230 | DispatchMessage(&msg); 231 | } 232 | 233 | DWORD current = timeGetTime(); 234 | DWORD delta = current - previous; 235 | 236 | if (delta >= frame_ms) { 237 | if (gIdleFunc) { 238 | gIdleFunc(delta); 239 | } 240 | previous = current; 241 | } 242 | } 243 | 244 | QUIT: 245 | 246 | timeEndPeriod(1); 247 | 248 | if (gCloseFunc) { 249 | gCloseFunc(); 250 | } 251 | 252 | gCtx.mDeviceContext->Release(); 253 | gCtx.mDevice->Release(); 254 | } 255 | 256 | bool DX_CreateSwapChain(DXGI_SWAP_CHAIN_DESC *scd, IDXGISwapChain **ppSwapChain) { 257 | // create the swap chain 258 | IDXGIDevice * dxgiDevice = nullptr; 259 | IDXGIAdapter * dxgiAdapter = nullptr; 260 | IDXGIFactory * dxgiFactory = nullptr; 261 | 262 | bool ok = false; 263 | 264 | do { 265 | 266 | if (DX_FAILED(gCtx.mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice))) { 267 | break; 268 | } 269 | DX_SET_DEBUG_NAME(dxgiDevice, "[CreateSwapChain]dxgiDevice"); 270 | 271 | if (DX_FAILED(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter))) { 272 | break; 273 | } 274 | DX_SET_DEBUG_NAME(dxgiAdapter, "[CreateSwapChain]dxgiAdapter"); 275 | 276 | if (DX_FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory))) { 277 | break; 278 | } 279 | DX_SET_DEBUG_NAME(dxgiFactory, "[CreateSwapChain]dxgiFactory"); 280 | 281 | if (DX_FAILED(dxgiFactory->CreateSwapChain(gCtx.mDevice, scd, ppSwapChain))) { 282 | break; 283 | } 284 | 285 | ok = true; 286 | 287 | } while (0); 288 | 289 | if (dxgiFactory) { 290 | dxgiFactory->Release(); 291 | } 292 | 293 | if (dxgiAdapter) { 294 | dxgiAdapter->Release(); 295 | } 296 | 297 | if (dxgiDevice) { 298 | dxgiDevice->Release(); 299 | } 300 | 301 | return ok; 302 | } 303 | 304 | bool DX_CreateRenderTargetView(IDXGISwapChain *pSwapChain, ID3D11RenderTargetView **ppRenderTargetView) { 305 | // create the render target view 306 | ID3D11Texture2D * back_buffer = nullptr; 307 | 308 | bool ok = false; 309 | 310 | do { 311 | 312 | if (DX_FAILED(pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&back_buffer)))) { 313 | break; 314 | } 315 | 316 | if (DX_FAILED(gCtx.mDevice->CreateRenderTargetView(back_buffer, NULL, ppRenderTargetView))) { 317 | break; 318 | } 319 | 320 | ok = true; 321 | 322 | } while (0); 323 | 324 | if (back_buffer) { 325 | back_buffer->Release(); 326 | } 327 | 328 | return ok; 329 | } 330 | 331 | bool DX_CreateTexture2D(ID3D11Device *dev, int width, int height, DXGI_FORMAT fmt, UINT bind_flags, const void *data, ID3D11Texture2D **ppTexture2D) { 332 | D3D11_TEXTURE2D_DESC td; 333 | memset(&td, 0, sizeof(td)); 334 | 335 | td.Width = width; 336 | td.Height = height; 337 | td.MipLevels = 1; 338 | td.ArraySize = 1; 339 | td.Format = fmt; 340 | td.SampleDesc.Count = 1; 341 | td.SampleDesc.Quality = 0; 342 | td.Usage = D3D11_USAGE_DEFAULT; 343 | td.BindFlags = bind_flags; 344 | td.CPUAccessFlags = 0; 345 | td.MiscFlags = 0; 346 | 347 | if (data) { 348 | D3D11_SUBRESOURCE_DATA sd; 349 | memset(&sd, 0, sizeof(sd)); 350 | 351 | sd.pSysMem = data; 352 | sd.SysMemPitch = width * 4; 353 | sd.SysMemSlicePitch = width * height * 4; 354 | 355 | if (DX_FAILED(dev->CreateTexture2D(&td, &sd, ppTexture2D))) { 356 | return false; 357 | } 358 | } 359 | else { 360 | if (DX_FAILED(dev->CreateTexture2D(&td, nullptr, ppTexture2D))) { 361 | return false; 362 | } 363 | } 364 | 365 | return true; 366 | } 367 | 368 | bool DX_CreateBuffer(ID3D11Device *dev, size_t size, UINT bind_flags, const void *data, ID3D11Buffer **ppBuffer) { 369 | D3D11_BUFFER_DESC bd; 370 | 371 | bd.ByteWidth = (UINT)size; 372 | bd.Usage = D3D11_USAGE_DEFAULT; 373 | bd.BindFlags = bind_flags; 374 | bd.CPUAccessFlags = 0; 375 | bd.MiscFlags = 0; 376 | bd.StructureByteStride = 0; 377 | 378 | D3D11_SUBRESOURCE_DATA rd; 379 | 380 | rd.pSysMem = data; 381 | rd.SysMemPitch = 0; 382 | rd.SysMemSlicePitch = 0; 383 | 384 | if (data) { 385 | D3D11_SUBRESOURCE_DATA sd; 386 | memset(&sd, 0, sizeof(sd)); 387 | 388 | sd.pSysMem = data; 389 | sd.SysMemPitch = 0; 390 | sd.SysMemSlicePitch = 0; 391 | 392 | if (DX_FAILED(dev->CreateBuffer(&bd, &sd, ppBuffer))) { 393 | return false; 394 | } 395 | } 396 | else { 397 | if (DX_FAILED(dev->CreateBuffer(&bd, nullptr, ppBuffer))) { 398 | return false; 399 | } 400 | } 401 | 402 | return true; 403 | } 404 | 405 | bool DX_Failed(HRESULT hr, const char_t *file, int line) { 406 | switch (hr) { 407 | case D3D11_ERROR_FILE_NOT_FOUND: 408 | Sys_Error(file, line, TXT_("D3D11_ERROR_FILE_NOT_FOUND\n")); 409 | return true; 410 | case D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS: 411 | Sys_Error(file, line, TXT_("D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS\n")); 412 | return true; 413 | case D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS: 414 | Sys_Error(file, line, TXT_("D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS\n")); 415 | return true; 416 | case D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD: 417 | Sys_Error(file, line, TXT_("D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD\n")); 418 | return true; 419 | case DXGI_ERROR_INVALID_CALL: // old: D3DERR_INVALIDCAL 420 | Sys_Error(file, line, TXT_("DXGI_ERROR_INVALID_CALL\n")); 421 | return true; 422 | case DXGI_ERROR_WAS_STILL_DRAWING: // old: D3DERR_WASSTILLDRAWING 423 | Sys_Error(file, line, TXT_("DXGI_ERROR_WAS_STILL_DRAWING\n")); 424 | return true; 425 | case E_FAIL: 426 | Sys_Error(file, line, TXT_("E_FAIL\n")); 427 | return true; 428 | case E_INVALIDARG: 429 | Sys_Error(file, line, TXT_("E_INVALIDARG\n")); 430 | return true; 431 | case E_OUTOFMEMORY: 432 | Sys_Error(file, line, TXT_("E_OUTOFMEMORY\n")); 433 | return true; 434 | case E_NOTIMPL: 435 | Sys_Error(file, line, TXT_("E_NOTIMPL\n")); 436 | return true; 437 | case S_FALSE: 438 | Sys_Error(file, line, TXT_("S_FALSE\n")); 439 | return true; 440 | case S_OK: 441 | return false; 442 | } 443 | 444 | if (FAILED(hr)) { 445 | Sys_Error(file, line, TXT_("D3D Error: UNKNOWN\n")); 446 | return true; 447 | } 448 | 449 | return true; 450 | } 451 | -------------------------------------------------------------------------------- /source/DXApp.h: -------------------------------------------------------------------------------- 1 | // DXApp.h 2 | 3 | #pragma once 4 | 5 | #include 6 | #include "Shared.h" 7 | 8 | struct d3d11_ctx_s { 9 | HWND mWnd; 10 | ID3D11Device * mDevice; 11 | ID3D11DeviceContext * mDeviceContext; 12 | }; 13 | 14 | #define DX_LEFT_BUTTON 1 15 | 16 | #define DX_DOWN 1 17 | #define DX_UP 2 18 | 19 | #define DX_FPS 60 20 | 21 | typedef void(*reshape_func_t)(int width, int height); 22 | typedef void(*mouse_func_t)(int button, int state, int x, int y); 23 | typedef void(*motion_func_t)(int x, int y); 24 | typedef void(*keyboard_func_t)(int key); 25 | typedef void(*idle_func_t)(int delta_ms); 26 | typedef void(*void_func_t)(); 27 | 28 | bool DX_CreateWindow(int width, int height, const wchar_t *title, d3d11_ctx_s **ctx); 29 | void DX_ReshapeFunc(reshape_func_t func); 30 | void DX_MouseFunc(mouse_func_t func); 31 | void DX_MotionFunc(motion_func_t func); 32 | void DX_KeyboardFunc(keyboard_func_t func); 33 | void DX_KeyboardUpFunc(keyboard_func_t func); 34 | void DX_DisplayFunc(void_func_t func); 35 | void DX_IdleFunc(idle_func_t func); 36 | void DX_CloseFunc(void_func_t func); 37 | void DX_MainLoop(); 38 | 39 | // utils 40 | void DX_GetClientCursorPos(POINT &pt); 41 | void DX_MoveCursorToClientCenter(); 42 | 43 | bool DX_CreateSwapChain(DXGI_SWAP_CHAIN_DESC *scd, IDXGISwapChain **ppSwapChain); 44 | bool DX_CreateRenderTargetView(IDXGISwapChain *pSwapChain, ID3D11RenderTargetView **ppRenderTargetView); 45 | bool DX_CreateTexture2D(ID3D11Device *dev, int width, int height, DXGI_FORMAT fmt, UINT bind_flags, const void *data, ID3D11Texture2D **ppTexture2D); 46 | bool DX_CreateBuffer(ID3D11Device *dev, size_t size, UINT bind_flags, const void *data, ID3D11Buffer **ppBuffer); 47 | 48 | bool DX_Failed(HRESULT hr, const char_t *file, int line); 49 | #define DX_FAILED(hr) DX_Failed(hr, __SRC_FILE__, __LINE__) 50 | #define DX_SAFE_RELEASE(obj) do { if (obj) { obj->Release(); obj = nullptr; } } while (0) 51 | 52 | #ifdef _DEBUG 53 | 54 | # define DX_SET_DEBUG_NAME(obj, name) \ 55 | do { \ 56 | const GUID WKPDID_D3DDebugObjectName_ = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; \ 57 | obj->SetPrivateData(WKPDID_D3DDebugObjectName_, (UINT)strlen(name), name); \ 58 | } while (0) 59 | 60 | #else 61 | 62 | # define DX_SET_DEBUG_NAME(obj, name) (void)0 63 | 64 | #endif // !_DEBUG 65 | -------------------------------------------------------------------------------- /source/Demo.cpp: -------------------------------------------------------------------------------- 1 | // Demo.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | Demo 8 | ================================================================================ 9 | */ 10 | Demo::Demo(): 11 | mDrawFlags(DRAW_SKYDOME | DRAW_CLOUD | DRAW_TERRAIN_SOLID), 12 | mMoveSpeed(10.0f), 13 | mMaxPixelError(DEFAILT_PIXEL_ERROR), 14 | mShowCursor(true), 15 | mLButtonDown(false), 16 | mPreviousMouseX(0), 17 | mPreviousMouseY(0), 18 | mViewCX(1), 19 | mViewCY(1), 20 | mSkipMouseMoveOnce(false) 21 | { 22 | memset(mKeyStates, 0, sizeof(mKeyStates)); 23 | } 24 | 25 | Demo::~Demo() { 26 | // do nothing 27 | } 28 | 29 | bool Demo::Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case) { 30 | if (!mRenderer.Init(ctx, res_dir, test_case)) { 31 | return false; 32 | } 33 | 34 | if (!mTerrain.Init(res_dir, test_case, mMaxPixelError)) { 35 | return false; 36 | } 37 | 38 | // set viewer to terrain center 39 | vec3_t init_view_pos; 40 | mTerrain.GetCenter(init_view_pos); 41 | init_view_pos[2] += 4.0f; 42 | mViewer.InitPos(init_view_pos); 43 | 44 | return true; 45 | } 46 | 47 | void Demo::Shutdown() { 48 | mTerrain.Shutdown(); 49 | mRenderer.Shutdown(); 50 | } 51 | 52 | void Demo::Resize(int width, int height) { 53 | mViewCX = max(width, 1); 54 | mViewCY = max(height, 1); 55 | mRenderer.Reshape(width, height); 56 | mTerrain.Reshape(width, height); 57 | } 58 | 59 | void Demo::Frame(const input_s *inputs, int count, float delta_seconds) { 60 | ProcessInput(inputs, count, delta_seconds); 61 | 62 | // update terrain 63 | const camera_s & cam = mViewer.GetCamera(); 64 | 65 | double t1 = Sys_GetRelativeTime(); 66 | mTerrain.Update(cam); 67 | double t2 = Sys_GetRelativeTime(); 68 | 69 | demo_info_s info; 70 | info.mUpdateTimeElapsed = t2 - t1; 71 | info.mMaxPixelError = mMaxPixelError; 72 | 73 | // draw 74 | mRenderer.UpdateRenderTerrain(mTerrain.GetRenderMesh()); 75 | mRenderer.Draw(delta_seconds, mDrawFlags, cam, info); 76 | } 77 | 78 | void Demo::ProcessInput(const input_s *inputs, int count, float delta_seconds) { 79 | Viewer::movement_delta_s movement_delta = { 0.0f }; 80 | 81 | for (int i = 0; i < count; ++i) { 82 | const input_s * input = inputs + i; 83 | 84 | if (input->mType == IN_LBUTTON_DOWN) { 85 | mLButtonDown = true; 86 | 87 | mPreviousMouseX = input->mParam1; 88 | mPreviousMouseY = input->mParam2; 89 | } 90 | else if (input->mType == IN_LBUTTON_UP) { 91 | mLButtonDown = false; 92 | 93 | mPreviousMouseX = input->mParam1; 94 | mPreviousMouseY = input->mParam2; 95 | } 96 | else if (input->mType == IN_MOUSE_MOVE) { 97 | int mouse_delta_x = input->mParam1 - mPreviousMouseX; 98 | int mouse_delta_y = input->mParam2 - mPreviousMouseY; 99 | 100 | mPreviousMouseX = input->mParam1; 101 | mPreviousMouseY = input->mParam2; 102 | 103 | if (mShowCursor) { 104 | if (mLButtonDown) { 105 | movement_delta.mDeltaYaw += -mouse_delta_x * MOUSE_SENSITIVITY; 106 | movement_delta.mDeltaPitch += -mouse_delta_y * MOUSE_SENSITIVITY; 107 | } 108 | } 109 | 110 | } 111 | else if (input->mType == IN_KEY_DOWN) { 112 | int key = input->mParam1; 113 | 114 | mKeyStates[key].mDown = true; 115 | 116 | // update display flags (first key down) 117 | if (mKeyStates[VK_F2].mDown && mKeyStates[VK_F2].mRepeat == 0) { 118 | ToggleFlags(mDrawFlags, DRAW_TERRAIN_SOLID); 119 | } 120 | else if (mKeyStates[VK_F3].mDown && mKeyStates[VK_F3].mRepeat == 0) { 121 | ToggleFlags(mDrawFlags, DRAW_TERRAIN_WIREFRAME); 122 | } 123 | else if (mKeyStates[VK_F4].mDown && mKeyStates[VK_F4].mRepeat == 0) { 124 | ToggleFlags(mDrawFlags, DRAW_SKYDOME); 125 | } 126 | else if (mKeyStates[VK_F5].mDown && mKeyStates[VK_F5].mRepeat == 0) { 127 | ToggleFlags(mDrawFlags, DRAW_CLOUD); 128 | } 129 | else if (mKeyStates[VK_SPACE].mDown && mKeyStates[VK_SPACE].mRepeat == 0) { 130 | mShowCursor = !mShowCursor; 131 | ShowCursor(mShowCursor); 132 | 133 | if (!mShowCursor) { 134 | mSkipMouseMoveOnce = true; 135 | } 136 | } 137 | else if (mKeyStates[VK_UP].mDown && mKeyStates[VK_UP].mRepeat == 0) { 138 | mMaxPixelError += 1.0f; 139 | if (mMaxPixelError > MAX_PIXEL_ERROR) { 140 | mMaxPixelError = MAX_PIXEL_ERROR; 141 | } 142 | mTerrain.UpdateMaxPixelError(mMaxPixelError); 143 | } 144 | else if (mKeyStates[VK_DOWN].mDown && mKeyStates[VK_DOWN].mRepeat == 0) { 145 | mMaxPixelError -= 1.0f; 146 | if (mMaxPixelError < MIN_PIXEL_ERROR) { 147 | mMaxPixelError = MIN_PIXEL_ERROR; 148 | } 149 | mTerrain.UpdateMaxPixelError(mMaxPixelError); 150 | } 151 | 152 | mKeyStates[key].mRepeat++; 153 | } 154 | else if (input->mType == IN_KEY_UP) { 155 | int key = input->mParam1; 156 | 157 | mKeyStates[key].mDown = false; 158 | mKeyStates[key].mRepeat = 0; 159 | } 160 | } 161 | 162 | // update move speed 163 | if (mKeyStates[VK_PRIOR].mDown) { 164 | mMoveSpeed += 1.0f; 165 | if (mMoveSpeed > MAX_MOVE_SPEED) { 166 | mMoveSpeed = MAX_MOVE_SPEED; 167 | } 168 | } 169 | else if (mKeyStates[VK_NEXT].mDown) { 170 | mMoveSpeed -= 1.0f; 171 | if (mMoveSpeed < MIN_MOVE_SPEED) { 172 | mMoveSpeed = MIN_MOVE_SPEED; 173 | } 174 | } 175 | 176 | if (!mShowCursor) { 177 | if (!mSkipMouseMoveOnce) { 178 | POINT pt; 179 | DX_GetClientCursorPos(pt); 180 | 181 | int mouse_delta_x = pt.x - mViewCX / 2; 182 | int mouse_delta_y = pt.y - mViewCY / 2; 183 | 184 | movement_delta.mDeltaYaw = -mouse_delta_x * MOUSE_SENSITIVITY; 185 | movement_delta.mDeltaPitch = -mouse_delta_y * MOUSE_SENSITIVITY; 186 | } 187 | else { 188 | mSkipMouseMoveOnce = false; 189 | } 190 | 191 | DX_MoveCursorToClientCenter(); 192 | } 193 | 194 | // update movement 195 | if (mKeyStates['W'].mDown) { 196 | movement_delta.mMoveForward = 1.0f; 197 | } 198 | 199 | if (mKeyStates['S'].mDown) { 200 | movement_delta.mMoveForward = -1.0f; 201 | } 202 | 203 | if (mKeyStates['A'].mDown) { 204 | movement_delta.mMoveRight = -1.0f; 205 | } 206 | 207 | if (mKeyStates['D'].mDown) { 208 | movement_delta.mMoveRight = 1.0f; 209 | } 210 | 211 | if (mKeyStates['Q'].mDown) { 212 | movement_delta.mMoveUp = 1.0f; 213 | } 214 | 215 | if (mKeyStates['Z'].mDown) { 216 | movement_delta.mMoveUp = -1.0f; 217 | } 218 | 219 | movement_delta.mMoveSpeed = mMoveSpeed; 220 | movement_delta.mDeltaSeconds = delta_seconds; 221 | 222 | mViewer.Update(movement_delta); 223 | } 224 | -------------------------------------------------------------------------------- /source/Demo.h: -------------------------------------------------------------------------------- 1 | // Demo.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | Demo 8 | ================================================================================ 9 | */ 10 | class Demo { 11 | public: 12 | 13 | Demo(); 14 | ~Demo(); 15 | 16 | bool Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case); 17 | void Shutdown(); 18 | 19 | void Resize(int width, int height); 20 | void Frame(const input_s *inputs, int count, float delta_seconds); 21 | 22 | private: 23 | 24 | struct key_state_s { 25 | bool mDown; 26 | int mRepeat; 27 | }; 28 | 29 | // control variables 30 | unsigned mDrawFlags; 31 | float mMoveSpeed; 32 | float mMaxPixelError; 33 | bool mShowCursor; 34 | 35 | // input states 36 | bool mLButtonDown; 37 | int mPreviousMouseX; 38 | int mPreviousMouseY; 39 | key_state_s mKeyStates[256]; 40 | 41 | int mViewCX; 42 | int mViewCY; 43 | bool mSkipMouseMoveOnce; 44 | 45 | // sub objects 46 | Viewer mViewer; 47 | Terrain mTerrain; 48 | Renderer mRenderer; 49 | 50 | void ProcessInput(const input_s *inputs, int count, float delta_seconds); 51 | }; 52 | -------------------------------------------------------------------------------- /source/GeoMipMapping.cpp: -------------------------------------------------------------------------------- 1 | // GeoMipMapping.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | GeoMipMapping 8 | ================================================================================ 9 | */ 10 | #define BLOCK_SIZE 16 // tune this: 16, 32 11 | static const float BLOCK_RADIUS = sqrtf(BLOCK_SIZE * BLOCK_SIZE) * 0.75f; // * 0.75f scale up a bit 12 | 13 | bool CheckTerrainSize(int x_size, int y_size) { 14 | if ((x_size - 1) < BLOCK_SIZE || (y_size - 1) < BLOCK_SIZE) { 15 | return false; 16 | } 17 | 18 | if (x_size > MAX_TERRAIN_SIZE || y_size > MAX_TERRAIN_SIZE) { 19 | return false; 20 | } 21 | 22 | if (((x_size - 1) % BLOCK_SIZE) != 0 || ((y_size - 1) % BLOCK_SIZE) != 0) { // must divide exactly by BLOCK_SIZE 23 | return false; 24 | } 25 | 26 | return true; 27 | } 28 | 29 | GeoMipMapping::GeoMipMapping() : 30 | mFovy(FOVY), 31 | mMaxPixelError(DEFAILT_PIXEL_ERROR), 32 | mLevels(0), 33 | mHeights(nullptr), 34 | mHeightsSizeX(1), 35 | mHeightsSizeY(1), 36 | mVertices(nullptr), 37 | mVerticesCount(0), 38 | mIndices(nullptr), 39 | mIndicesCount(0), 40 | mErrorBuffer(nullptr), 41 | mDSquareBuffer(nullptr), 42 | mBlocks(nullptr), 43 | mBlocksXCount(0), 44 | mBlocksYCount(0), 45 | mBufferFull(false), 46 | mViewWidth(1), 47 | mViewHeight(1), 48 | mTriangleCount(0) 49 | { 50 | mRenderMesh.mVertices = nullptr; 51 | mRenderMesh.mVerticesCount = 0; 52 | mRenderMesh.mIndices = nullptr; 53 | mRenderMesh.mIndicesCount = 0; 54 | } 55 | 56 | GeoMipMapping::~GeoMipMapping() { 57 | // do nothing 58 | } 59 | 60 | void GeoMipMapping::Build(const height_field_s &hf, float fovy, int view_width, int view_height, float max_pixel_error) { 61 | mFovy = fovy; 62 | mViewWidth = view_width; 63 | mViewHeight = view_height; 64 | mMaxPixelError = max_pixel_error; 65 | 66 | mHeights = (float*)malloc(sizeof(float) * hf.mSizeX * hf.mSizeY); 67 | memcpy(mHeights, hf.mHeights, sizeof(float) * hf.mSizeX * hf.mSizeY); 68 | mHeightsSizeX = hf.mSizeX; 69 | mHeightsSizeY = hf.mSizeY; 70 | 71 | mVertices = (vertex_pos_s*)malloc(sizeof(vertex_pos_s) * MAX_DRAW_VERT_COUNT); 72 | mIndices = (unsigned int*)malloc(sizeof(unsigned int) * MAX_DRAW_IDX_COUNT); 73 | mVerticesCount = 0; 74 | mIndicesCount = 0; 75 | 76 | mLevels = 1; 77 | int block_size = BLOCK_SIZE; 78 | while (block_size >= 2) { 79 | block_size >>= 1; 80 | mLevels++; 81 | } 82 | 83 | mBlocksXCount = (mHeightsSizeX - 1) / BLOCK_SIZE; 84 | mBlocksYCount = (mHeightsSizeY - 1) / BLOCK_SIZE; 85 | int block_count = mBlocksXCount * mBlocksYCount; 86 | 87 | mBlocks = (block_s*)malloc(sizeof(block_s) * block_count); 88 | mDSquareBuffer = (float*)malloc(sizeof(float) * block_count * (mLevels - 1)); 89 | mErrorBuffer = (float*)malloc(sizeof(float) * block_count * (mLevels - 1)); 90 | 91 | for (int block_y = 0; block_y < mBlocksYCount; ++block_y) { 92 | for (int block_x = 0; block_x < mBlocksXCount; ++block_x) { 93 | block_s * block = mBlocks + block_y * mBlocksXCount + block_x; 94 | 95 | int center_x = block_x * BLOCK_SIZE + BLOCK_SIZE / 2; 96 | int center_y = block_y * BLOCK_SIZE + BLOCK_SIZE / 2; 97 | 98 | // find min z, max z in current block 99 | float min_z = 99999999.0f; 100 | float max_z = -99999999.0f; 101 | for (int y = block_y * BLOCK_SIZE; y <= (block_y + 1) * BLOCK_SIZE; ++y) { 102 | for (int x = block_x * BLOCK_SIZE; x <= (block_x + 1) * BLOCK_SIZE; ++x) { 103 | float z = mHeights[y * mHeightsSizeX + x]; 104 | 105 | if (z > max_z) { 106 | max_z = z; 107 | } 108 | 109 | if (z < min_z) { 110 | min_z = z; 111 | } 112 | } 113 | } 114 | 115 | float center_z = (min_z + max_z) * 0.5f; // block bouding box center 116 | 117 | block->mXIndex = block_x; 118 | block->mYIndex = block_y; 119 | Vec3Set(block->mCenter, (float)center_x, (float)center_y, center_z); 120 | block->mDisplayLevel = 0; 121 | block->mDSquareList = mDSquareBuffer + (block_y * mBlocksXCount + block_x) * (mLevels - 1); 122 | block->mErrorList = mErrorBuffer + (block_y * mBlocksXCount + block_x) * (mLevels - 1); 123 | 124 | CalcBlockErrorList(block); 125 | } 126 | } 127 | 128 | BuildBlockDList(); 129 | } 130 | 131 | void GeoMipMapping::Clear() { 132 | SAFE_FREE(mDSquareBuffer); 133 | SAFE_FREE(mErrorBuffer); 134 | SAFE_FREE(mBlocks); 135 | SAFE_FREE(mIndices); 136 | SAFE_FREE(mVertices); 137 | SAFE_FREE(mHeights); 138 | } 139 | 140 | void GeoMipMapping::Reshape(int view_width, int view_height) { 141 | mViewWidth = view_width; 142 | mViewHeight = view_height; 143 | BuildBlockDList(); 144 | } 145 | 146 | void GeoMipMapping::UpdateMaxPixelError(float max_pixel_error) { 147 | mMaxPixelError = max_pixel_error; 148 | BuildBlockDList(); 149 | } 150 | 151 | void GeoMipMapping::Update(const camera_s &cam) { 152 | mFrustumPlane.Setup(mViewWidth, mViewHeight, cam); 153 | 154 | mTriangleCount = 0; 155 | // setup display level 156 | for (int i = 0; i < mBlocksXCount * mBlocksYCount; ++i) { 157 | block_s * block = mBlocks + i; 158 | 159 | UpdateBlock(mBlocks + i, cam); 160 | 161 | if (mFrustumPlane.CullHorizontalCircle(block->mCenter, BLOCK_RADIUS)) { 162 | block->mVisible = false; 163 | } 164 | else { 165 | block->mVisible = true; 166 | 167 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 168 | mTriangleCount += display_quad_dim * display_quad_dim * 2; 169 | } 170 | } 171 | 172 | mVerticesCount = 0; 173 | mIndicesCount = 0; 174 | 175 | // setup draw vertices and indices 176 | mBufferFull = false; 177 | for (int i = 0; i < mBlocksXCount * mBlocksYCount; ++i) { 178 | block_s * block = mBlocks + i; 179 | 180 | if (mBufferFull) { // run out of vertex or index buffer 181 | break; 182 | } 183 | 184 | if (block->mVisible) { 185 | SetupRenderMeshByBlock(block); 186 | } 187 | } 188 | 189 | mRenderMesh.mVertices = mVertices; 190 | mRenderMesh.mVerticesCount = mVerticesCount; 191 | mRenderMesh.mIndices = mIndices; 192 | mRenderMesh.mIndicesCount = mIndicesCount; 193 | mRenderMesh.mTriangleCount = mTriangleCount; 194 | } 195 | 196 | const mesh_s & GeoMipMapping::GetRenderMesh() const { 197 | return mRenderMesh; 198 | } 199 | 200 | /* 201 | 202 | '.' are eliminated vertices 203 | '+' are keep vertices 204 | 205 | + -- . -- + -- . -- + row 4 206 | | \ | \ | 207 | . . . . . row 3 208 | | \ | \ | 209 | + -- . -- + -- . -- + row 2 210 | | \ | \ | 211 | . . . . . row 1 212 | | \ | \ | 213 | + -- . -- + -- . -- + row 0 214 | 215 | */ 216 | 217 | // make sure higher level has larger error 218 | #define MIN_LEVEL_ERROR_TIMES 1.5f 219 | 220 | void GeoMipMapping::CalcBlockErrorList(block_s *block) { 221 | int vert_start_x = block->mXIndex * BLOCK_SIZE; 222 | int vert_start_y = block->mYIndex * BLOCK_SIZE; 223 | 224 | float prior_level_max_error = 0.0f; 225 | for (int i = 1; i < mLevels; ++i) { 226 | float current_level_max_error = 0.0f; 227 | 228 | int step = 1 << i; 229 | int half_step = step / 2; 230 | 231 | // even rows 232 | for (int y = vert_start_y; y <= vert_start_y + BLOCK_SIZE; y += step) { 233 | 234 | for (int x = vert_start_x + half_step; x <= vert_start_x + BLOCK_SIZE - half_step; x += step) { 235 | 236 | float height = mHeights[y * mHeightsSizeX + x]; 237 | float height_lf = mHeights[y * mHeightsSizeX + x - half_step]; 238 | float height_rt = mHeights[y * mHeightsSizeX + x + half_step]; 239 | float simplified_height = (height_lf + height_rt) * 0.5f; 240 | float error = fabsf(height - simplified_height); 241 | 242 | if (error > current_level_max_error) { 243 | current_level_max_error = error; 244 | } 245 | } 246 | } 247 | 248 | // odd rows 249 | for (int y = vert_start_y + half_step; y <= vert_start_y + BLOCK_SIZE - half_step; y += step) { 250 | 251 | for (int x = vert_start_x; x <= vert_start_x + BLOCK_SIZE; x += step) { 252 | 253 | float height = mHeights[y * mHeightsSizeX + x]; 254 | float height_tp = mHeights[(y + half_step) * mHeightsSizeX + x]; 255 | float height_bt = mHeights[(y - half_step) * mHeightsSizeX + x]; 256 | float simplified_height = (height_tp + height_bt) * 0.5f; 257 | float error = fabsf(height - simplified_height); 258 | 259 | if (error > current_level_max_error) { 260 | current_level_max_error = error; 261 | } 262 | } 263 | } 264 | 265 | // center 266 | for (int y = vert_start_y + half_step; y <= vert_start_y + BLOCK_SIZE - half_step; y += step) { 267 | 268 | for (int x = vert_start_x + half_step; x <= vert_start_x + BLOCK_SIZE - half_step; x += step) { 269 | 270 | float height = mHeights[y * mHeightsSizeX + x]; 271 | float height_tp_lf = mHeights[(y + half_step) * mHeightsSizeX + x - half_step]; 272 | float height_bt_rt = mHeights[(y - half_step) * mHeightsSizeX + x + half_step]; 273 | float simplified_height = (height_tp_lf + height_bt_rt) * 0.5f; 274 | float error = fabsf(height - simplified_height); 275 | 276 | if (error > current_level_max_error) { 277 | current_level_max_error = error; 278 | } 279 | } 280 | 281 | } 282 | 283 | if (current_level_max_error < prior_level_max_error * MIN_LEVEL_ERROR_TIMES) { 284 | current_level_max_error = prior_level_max_error * MIN_LEVEL_ERROR_TIMES; 285 | } 286 | 287 | block->mErrorList[i - 1] = current_level_max_error; 288 | prior_level_max_error = current_level_max_error; 289 | } 290 | } 291 | 292 | void GeoMipMapping::BuildBlockDList() { 293 | float t = NEAR_CLIP_PLANE * tanf(Deg2Rad(mFovy * 0.5f)); 294 | float A = NEAR_CLIP_PLANE / t; 295 | float T = 2.0f * mMaxPixelError / mViewHeight; 296 | float C = A / T; 297 | 298 | for (int i = 0; i < mBlocksXCount * mBlocksYCount; ++i) { 299 | block_s * block = mBlocks + i; 300 | 301 | for (int j = 1; j < mLevels; ++j) { 302 | float err = block->mErrorList[j - 1]; 303 | float d = (err * err) * (C * C); // squared 304 | block->mDSquareList[j - 1] = d; 305 | } 306 | } 307 | 308 | #ifdef _DEBUG 309 | 310 | /* // dump error and d list 311 | FILE * f = nullptr; 312 | fopen_s(&f, "errorlist.txt", "w"); 313 | for (int i = 0; i < mBlocksXCount * mBlocksYCount; ++i) { 314 | block_s * block = mBlocks + i; 315 | 316 | fprintf_s(f, "%03d-%03d ", block->mXIndex, block->mYIndex); 317 | 318 | for (int j = 1; j < mLevels; ++j) { 319 | float err = block->mErrorList[j - 1]; 320 | float d = block->mDSquareList[j - 1]; 321 | 322 | fprintf_s(f, "(%12.4f,%12.4f) ", err, d); 323 | } 324 | 325 | fprintf_s(f, "\n"); 326 | } 327 | fclose(f); 328 | //*/ 329 | 330 | #endif 331 | } 332 | 333 | void GeoMipMapping::UpdateBlock(block_s *block, const camera_s &cam) { 334 | vec3_t horizontal_delta_to_view; 335 | 336 | horizontal_delta_to_view[0] = cam.mPos[0] - block->mCenter[0]; 337 | horizontal_delta_to_view[1] = cam.mPos[1] - block->mCenter[1]; 338 | horizontal_delta_to_view[2] = 0.0f; // omit vertical difference 339 | 340 | float d_square = Vec3SquareLength(horizontal_delta_to_view); 341 | 342 | block->mDisplayLevel = 0; 343 | for (int i = 1; i < mLevels; ++i) { 344 | if (d_square > block->mDSquareList[i - 1]) { 345 | block->mDisplayLevel = i; 346 | } 347 | else { 348 | break; 349 | } 350 | } 351 | } 352 | 353 | void GeoMipMapping::SetupRenderMeshByBlock(block_s *block) { 354 | // check free buffer capacity 355 | 356 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 357 | int need_vertices = Square(display_quad_dim + 1); 358 | if ((need_vertices + mVerticesCount) > MAX_DRAW_VERT_COUNT) { 359 | mBufferFull = true; 360 | return; 361 | } 362 | 363 | int need_max_indices = (display_quad_dim * (display_quad_dim + 1) * 2) + display_quad_dim; /* plus restart index */ 364 | 365 | need_max_indices += (display_quad_dim / 2) * 4; // possible edge restart index 366 | 367 | if ((need_max_indices + mIndicesCount) > MAX_DRAW_IDX_COUNT) { 368 | mBufferFull = true; 369 | return; 370 | } 371 | 372 | int vert_start_x = block->mXIndex * BLOCK_SIZE; 373 | int vert_start_y = block->mYIndex * BLOCK_SIZE; 374 | int vert_step = 1 << block->mDisplayLevel; 375 | 376 | unsigned global_index_offset = (unsigned)mVerticesCount; 377 | 378 | // setup vertices 379 | for (int y = vert_start_y; y <= vert_start_y + BLOCK_SIZE; y += vert_step) { 380 | for (int x = vert_start_x; x <= vert_start_x + BLOCK_SIZE; x += vert_step) { 381 | Vec3Set(mVertices[mVerticesCount++].mPosition, (float)x, (float)y, mHeights[y * mHeightsSizeX + x]); 382 | } 383 | } 384 | 385 | // setup indices 386 | if (block->mDisplayLevel == mLevels - 1) { 387 | mIndices[mIndicesCount++] = RESTART_INDEX; 388 | 389 | mIndices[mIndicesCount++] = 2 + global_index_offset; 390 | mIndices[mIndicesCount++] = 0 + global_index_offset; 391 | mIndices[mIndicesCount++] = 3 + global_index_offset; 392 | mIndices[mIndicesCount++] = 1 + global_index_offset; 393 | 394 | return; 395 | } 396 | 397 | /* 398 | 399 | topology, front face is counter-clock wise 400 | ________________________________________________ 401 | | /| /| /| /| /| /| /| /| 402 | | / | / | / | / | / | / | / | / | 403 | | / | / | / | / | / | / | / | / | 404 | | / | / | / | / | / | / | / | / | 405 | |/____|/____|/____|/____|/____|/____|/____|/____| 406 | 407 | */ 408 | for (int row = 1; row < display_quad_dim - 1; ++row) { 409 | mIndices[mIndicesCount++] = RESTART_INDEX; 410 | 411 | for (int col = 1; col < display_quad_dim; ++col) { 412 | int local_idx0 = (row + 1) * (display_quad_dim + 1) + col; 413 | int local_idx1 = local_idx0 - display_quad_dim - 1; 414 | 415 | mIndices[mIndicesCount++] = local_idx0 + global_index_offset; 416 | mIndices[mIndicesCount++] = local_idx1 + global_index_offset; 417 | } 418 | } 419 | 420 | // check neighbors 421 | 422 | // bottom 423 | if (block->mYIndex > 0) { // has bottom neighbor 424 | block_s * bottom_neighbor = mBlocks + (block->mYIndex - 1) * mBlocksXCount + block->mXIndex; 425 | if (bottom_neighbor->mDisplayLevel > block->mDisplayLevel) { 426 | SetupBottomEdgeFixGap(block, bottom_neighbor, global_index_offset); 427 | } 428 | else { 429 | SetupBottomEdgeNormally(block, global_index_offset); 430 | } 431 | } 432 | else { 433 | SetupBottomEdgeNormally(block, global_index_offset); 434 | } 435 | 436 | // right 437 | if (block->mXIndex < mBlocksXCount - 1) { 438 | block_s * right_neighbor = mBlocks + block->mYIndex * mBlocksXCount + block->mXIndex + 1; 439 | if (right_neighbor->mDisplayLevel > block->mDisplayLevel) { 440 | SetupRightEdgeFixGap(block, right_neighbor, global_index_offset); 441 | } 442 | else { 443 | SetupRightEdgeNormally(block, global_index_offset); 444 | } 445 | } 446 | else { 447 | SetupRightEdgeNormally(block, global_index_offset); 448 | } 449 | 450 | // top 451 | if (block->mYIndex < mBlocksYCount - 1) { 452 | block_s * top_neighbor = mBlocks + (block->mYIndex + 1) * mBlocksXCount + block->mXIndex; 453 | if (top_neighbor->mDisplayLevel > block->mDisplayLevel) { 454 | SetupTopEdgeFixGap(block, top_neighbor, global_index_offset); 455 | } 456 | else { 457 | SetupTopEdgeNormally(block, global_index_offset); 458 | } 459 | } 460 | else { 461 | SetupTopEdgeNormally(block, global_index_offset); 462 | } 463 | 464 | // left 465 | if (block->mXIndex > 0) { 466 | block_s * left_neighbor = mBlocks + block->mYIndex * mBlocksXCount + block->mXIndex - 1; 467 | if (left_neighbor->mDisplayLevel > block->mDisplayLevel) { 468 | SetupLeftEdgeFixGap(block, left_neighbor, global_index_offset); 469 | } 470 | else { 471 | SetupLeftEdgeNormally(block, global_index_offset); 472 | } 473 | } 474 | else { 475 | SetupLeftEdgeNormally(block, global_index_offset); 476 | } 477 | } 478 | 479 | /* 480 | 481 | bottom edge topology 482 | 483 | <------ 484 | ______ 485 | /|\ | \|\ 486 | /_|_\|_\|_\ 487 | 488 | */ 489 | void GeoMipMapping::SetupBottomEdgeNormally(block_s *block, unsigned int global_index_offset) { 490 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 491 | 492 | mIndices[mIndicesCount++] = RESTART_INDEX; 493 | 494 | mIndices[mIndicesCount++] = display_quad_dim + global_index_offset; 495 | for (int col = display_quad_dim - 1; col >= 1; --col) { 496 | int local_idx0 = display_quad_dim + 1 + col; 497 | int local_idx1 = local_idx0 - display_quad_dim - 1; 498 | 499 | mIndices[mIndicesCount++] = local_idx0 + global_index_offset; 500 | mIndices[mIndicesCount++] = local_idx1 + global_index_offset; 501 | } 502 | mIndices[mIndicesCount++] = 0 + global_index_offset; 503 | } 504 | 505 | /* 506 | 507 | right edge topology 508 | 509 | | 510 | | 511 | \|/ 512 | 513 | /| 514 | /_| 515 | | /| 516 | |/_| 517 | | /| 518 | |/_| 519 | \ | 520 | \| 521 | 522 | */ 523 | void GeoMipMapping::SetupRightEdgeNormally(block_s *block, unsigned int global_index_offset) { 524 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 525 | 526 | mIndices[mIndicesCount++] = RESTART_INDEX; 527 | 528 | int last_local_idx = Square(display_quad_dim + 1) - 1; 529 | 530 | mIndices[mIndicesCount++] = last_local_idx + global_index_offset; 531 | for (int row = display_quad_dim - 1; row >= 1; --row) { 532 | int local_idx0 = (display_quad_dim + 1) * (row + 1) - 2; 533 | int local_idx1 = local_idx0 + 1; 534 | 535 | mIndices[mIndicesCount++] = local_idx0 + global_index_offset; 536 | mIndices[mIndicesCount++] = local_idx1 + global_index_offset; 537 | } 538 | mIndices[mIndicesCount++] = display_quad_dim + global_index_offset; 539 | } 540 | 541 | /* 542 | 543 | top edge topology 544 | 545 | ------> 546 | 547 | ___________ 548 | \ |\ |\ | / 549 | \|_\|_\|/ 550 | 551 | */ 552 | void GeoMipMapping::SetupTopEdgeNormally(block_s *block, unsigned int global_index_offset) { 553 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 554 | 555 | mIndices[mIndicesCount++] = RESTART_INDEX; 556 | 557 | mIndices[mIndicesCount++] = display_quad_dim * (display_quad_dim + 1) + global_index_offset; 558 | for (int col = 1; col < display_quad_dim; ++col) { 559 | int local_idx0 = (display_quad_dim - 1) * (display_quad_dim + 1) + col; 560 | int local_idx1 = local_idx0 + display_quad_dim + 1; 561 | 562 | mIndices[mIndicesCount++] = local_idx0 + global_index_offset; 563 | mIndices[mIndicesCount++] = local_idx1 + global_index_offset; 564 | } 565 | int last_local_idx = Square(display_quad_dim + 1) - 1; 566 | mIndices[mIndicesCount++] = last_local_idx + global_index_offset; 567 | } 568 | 569 | /* 570 | 571 | left edge topology 572 | 573 | /|\ 574 | | 575 | | 576 | 577 | |\ 578 | |_\ 579 | | /| 580 | |/_| 581 | | /| 582 | |/_| 583 | | / 584 | |/ 585 | 586 | */ 587 | 588 | void GeoMipMapping::SetupLeftEdgeNormally(block_s *block, unsigned int global_index_offset) { 589 | int display_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 590 | 591 | mIndices[mIndicesCount++] = RESTART_INDEX; 592 | mIndices[mIndicesCount++] = 0 + global_index_offset; 593 | for (int row = 1; row < display_quad_dim; ++row) { 594 | int local_idx0 = (display_quad_dim + 1) * row + 1; 595 | int local_idx1 = local_idx0 - 1; 596 | 597 | mIndices[mIndicesCount++] = local_idx0 + global_index_offset; 598 | mIndices[mIndicesCount++] = local_idx1 + global_index_offset; 599 | } 600 | mIndices[mIndicesCount++] = display_quad_dim * (display_quad_dim + 1) + global_index_offset; 601 | } 602 | 603 | // fix gaps 604 | 605 | void GeoMipMapping::SetupBottomEdgeFixGap(block_s *block, block_s *bottom_neighbor, unsigned int global_index_offset) { 606 | int block_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 607 | int neighbor_quad_dim = BLOCK_SIZE >> bottom_neighbor->mDisplayLevel; 608 | 609 | int t = block_quad_dim / neighbor_quad_dim; 610 | 611 | int x_max, x_min; 612 | 613 | bool ret = false; 614 | 615 | // right corner 616 | x_max = neighbor_quad_dim * t; 617 | x_min = x_max - t; 618 | 619 | mIndices[mIndicesCount++] = RESTART_INDEX; 620 | for (int x = x_max; x > x_min; --x) { 621 | if (x - 1 <= 0) { 622 | ret = true; 623 | break; 624 | } 625 | 626 | int idx0 = x_max; 627 | int idx1 = (x - 1) + block_quad_dim + 1; 628 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 629 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 630 | } 631 | mIndices[mIndicesCount++] = x_min + global_index_offset; 632 | 633 | if (ret) { 634 | return; 635 | } 636 | 637 | // left corner 638 | x_max = t; 639 | x_min = 0; 640 | 641 | mIndices[mIndicesCount++] = RESTART_INDEX; 642 | for (int x = x_max; x > x_min; --x) { 643 | int idx0 = x_max; 644 | int idx1 = x + block_quad_dim + 1; 645 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 646 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 647 | } 648 | mIndices[mIndicesCount++] = x_min + global_index_offset; 649 | 650 | // bottom edge 651 | for (int i = neighbor_quad_dim - 2; i >= 1; --i) { 652 | x_max = (i + 1) * t; 653 | x_min = x_max - t; 654 | 655 | mIndices[mIndicesCount++] = RESTART_INDEX; 656 | for (int x = x_max; x >= x_min; --x) { 657 | int idx0 = x_max; 658 | int idx1 = x + block_quad_dim + 1; 659 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 660 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 661 | } 662 | mIndices[mIndicesCount++] = x_min + global_index_offset; 663 | } 664 | } 665 | 666 | void GeoMipMapping::SetupRightEdgeFixGap(block_s *block, block_s *right_neighbor, unsigned int global_index_offset) { 667 | int block_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 668 | int neighbor_quad_dim = BLOCK_SIZE >> right_neighbor->mDisplayLevel; 669 | 670 | int t = block_quad_dim / neighbor_quad_dim; 671 | 672 | int y_max, y_min; 673 | bool ret = false; 674 | 675 | // top corner 676 | y_max = neighbor_quad_dim * t; 677 | y_min = y_max - t; 678 | 679 | mIndices[mIndicesCount++] = RESTART_INDEX; 680 | for (int y = y_max; y > y_min; --y) { 681 | if (y - 1 == 0) { 682 | ret = true; 683 | break; 684 | } 685 | 686 | int idx0 = y_max * (block_quad_dim + 1) + (block_quad_dim + 1) - 1; 687 | int idx1 = (y - 1) * (block_quad_dim + 1) + (block_quad_dim + 1) - 1 - 1; 688 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 689 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 690 | } 691 | mIndices[mIndicesCount++] = y_min * (block_quad_dim + 1) + (block_quad_dim + 1) - 1 + global_index_offset; 692 | 693 | if (ret) { 694 | return; 695 | } 696 | 697 | // bottom corner 698 | y_max = t; 699 | y_min = y_max - t; 700 | 701 | mIndices[mIndicesCount++] = RESTART_INDEX; 702 | for (int y = y_max; y > y_min; --y) { 703 | int idx0 = y_max * (block_quad_dim + 1) + (block_quad_dim + 1) - 1; 704 | int idx1 = y * (block_quad_dim + 1) + (block_quad_dim + 1) - 1 - 1; 705 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 706 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 707 | } 708 | mIndices[mIndicesCount++] = y_min * (block_quad_dim + 1) + (block_quad_dim + 1) - 1 + global_index_offset; 709 | 710 | // right edge 711 | for (int i = neighbor_quad_dim - 2; i >= 1; --i) { 712 | y_max = (i + 1) * t; 713 | y_min = y_max - t; 714 | 715 | mIndices[mIndicesCount++] = RESTART_INDEX; 716 | for (int y = y_max; y >= y_min; --y) { 717 | int idx0 = (y_max + 1) * (block_quad_dim + 1) - 1; 718 | int idx1 = (y + 1) * (block_quad_dim + 1) - 1 - 1; 719 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 720 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 721 | } 722 | mIndices[mIndicesCount++] = (y_min + 1) * (block_quad_dim + 1) - 1 + global_index_offset; 723 | } 724 | } 725 | 726 | void GeoMipMapping::SetupTopEdgeFixGap(block_s *block, block_s *top_neighbor, unsigned int global_index_offset) { 727 | int block_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 728 | int neighbor_quad_dim = BLOCK_SIZE >> top_neighbor->mDisplayLevel; 729 | 730 | int t = block_quad_dim / neighbor_quad_dim; 731 | 732 | int x_max, x_min; 733 | bool ret = false; 734 | 735 | // left corner 736 | x_min = 0; 737 | x_max = x_min + t; 738 | 739 | mIndices[mIndicesCount++] = RESTART_INDEX; 740 | for (int x = x_min; x < x_max; ++x) { 741 | if (x + 1 >= neighbor_quad_dim * t) { 742 | ret = true; 743 | break; 744 | } 745 | 746 | int idx0 = x_min + block_quad_dim * (block_quad_dim + 1); 747 | int idx1 = (x + 1) + block_quad_dim * (block_quad_dim + 1) - block_quad_dim - 1; 748 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 749 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 750 | } 751 | mIndices[mIndicesCount++] = x_max + block_quad_dim * (block_quad_dim + 1) + global_index_offset; 752 | 753 | if (ret) { 754 | return; 755 | } 756 | 757 | // right corner 758 | x_min = (neighbor_quad_dim - 1) * t; 759 | x_max = x_min + t; 760 | 761 | mIndices[mIndicesCount++] = RESTART_INDEX; 762 | for (int x = x_min; x < x_max; ++x) { 763 | int idx0 = x_min + block_quad_dim * (block_quad_dim + 1); 764 | int idx1 = x + block_quad_dim * (block_quad_dim + 1) - block_quad_dim - 1; 765 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 766 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 767 | } 768 | mIndices[mIndicesCount++] = x_max + block_quad_dim * (block_quad_dim + 1) + global_index_offset; 769 | 770 | // top edge 771 | for (int i = 1; i <= neighbor_quad_dim - 2; ++i) { 772 | x_min = i * t; 773 | x_max = x_min + t; 774 | 775 | mIndices[mIndicesCount++] = RESTART_INDEX; 776 | for (int x = x_min; x <= x_max; ++x) { 777 | int idx0 = x_min + block_quad_dim * (block_quad_dim + 1); 778 | int idx1 = x + block_quad_dim * (block_quad_dim + 1) - block_quad_dim - 1; 779 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 780 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 781 | } 782 | mIndices[mIndicesCount++] = x_max + block_quad_dim * (block_quad_dim + 1) + global_index_offset; 783 | } 784 | } 785 | 786 | void GeoMipMapping::SetupLeftEdgeFixGap(block_s *block, block_s *left_neighbor, unsigned int global_index_offset) { 787 | int block_quad_dim = BLOCK_SIZE >> block->mDisplayLevel; 788 | int neighbor_quad_dim = BLOCK_SIZE >> left_neighbor->mDisplayLevel; 789 | 790 | int t = block_quad_dim / neighbor_quad_dim; 791 | 792 | int y_max, y_min; 793 | 794 | bool ret = false; 795 | 796 | // bottom corner 797 | y_min = 0; 798 | y_max = t; 799 | 800 | mIndices[mIndicesCount++] = RESTART_INDEX; 801 | for (int y = y_min; y < y_max; ++y) { 802 | if (y + 1 >= neighbor_quad_dim * t) { 803 | ret = true; 804 | break; 805 | } 806 | 807 | int idx1 = (y + 1) * (block_quad_dim + 1) + 1; 808 | int idx0 = y_min * (block_quad_dim + 1); 809 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 810 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 811 | } 812 | mIndices[mIndicesCount++] = y_max * (block_quad_dim + 1) + global_index_offset; 813 | 814 | if (ret) { 815 | return; 816 | } 817 | 818 | // top corner 819 | y_min = (neighbor_quad_dim - 1) * t; 820 | y_max = y_min + t; 821 | 822 | mIndices[mIndicesCount++] = RESTART_INDEX; 823 | for (int y = y_min; y < y_max; ++y) { 824 | int idx1 = y * (block_quad_dim + 1) + 1; 825 | int idx0 = y_min * (block_quad_dim + 1); 826 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 827 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 828 | } 829 | mIndices[mIndicesCount++] = y_max * (block_quad_dim + 1) + global_index_offset; 830 | 831 | // left edge 832 | for (int i = 1; i <= neighbor_quad_dim - 2; ++i) { 833 | y_min = i * t; 834 | y_max = y_min + t; 835 | 836 | mIndices[mIndicesCount++] = RESTART_INDEX; 837 | for (int y = y_min; y <= y_max; ++y) { 838 | int idx1 = y * (block_quad_dim + 1) + 1; 839 | int idx0 = y_min * (block_quad_dim + 1); 840 | mIndices[mIndicesCount++] = idx0 + global_index_offset; 841 | mIndices[mIndicesCount++] = idx1 + global_index_offset; 842 | } 843 | mIndices[mIndicesCount++] = y_max * (block_quad_dim + 1) + global_index_offset; 844 | } 845 | } 846 | -------------------------------------------------------------------------------- /source/GeoMipMapping.h: -------------------------------------------------------------------------------- 1 | // GeoMipMapping.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | GeoMipMapping 8 | ================================================================================ 9 | */ 10 | struct height_field_s { 11 | float * mHeights; 12 | int mSizeX; 13 | int mSizeY; 14 | }; 15 | 16 | class GeoMipMapping { 17 | public: 18 | GeoMipMapping(); 19 | ~GeoMipMapping(); 20 | 21 | void Build(const height_field_s &hf, float fovy, int view_width, int view_height, float max_pixel_error); 22 | void Clear(); 23 | 24 | void Reshape(int view_width, int view_height); 25 | void UpdateMaxPixelError(float max_pixel_error); 26 | 27 | void Update(const camera_s &cam); 28 | const mesh_s & GetRenderMesh() const; 29 | 30 | private: 31 | 32 | struct block_s { 33 | bool mVisible; 34 | int mXIndex; // block's x index 35 | int mYIndex; // block's y index 36 | vec3_t mCenter; // bounding box center 37 | int mDisplayLevel; // level 0 is finest 38 | float * mErrorList; // error in object space 39 | float * mDSquareList; // Dn 40 | }; 41 | 42 | float mFovy; 43 | float mMaxPixelError; 44 | 45 | int mLevels; // level count 46 | float * mHeights; 47 | int mHeightsSizeX; 48 | int mHeightsSizeY; 49 | vertex_pos_s * mVertices; 50 | int mVerticesCount; 51 | unsigned int * mIndices; 52 | int mIndicesCount; 53 | mesh_s mRenderMesh; 54 | float * mErrorBuffer; 55 | float * mDSquareBuffer; 56 | block_s * mBlocks; 57 | int mBlocksXCount; 58 | int mBlocksYCount; 59 | bool mBufferFull; 60 | int mTriangleCount; 61 | 62 | int mViewWidth; 63 | int mViewHeight; 64 | frustum_plane_s mFrustumPlane; 65 | 66 | void CalcBlockErrorList(block_s *block); 67 | void BuildBlockDList(); 68 | void UpdateBlock(block_s *block, const camera_s &cam); 69 | void SetupRenderMeshByBlock(block_s *block); 70 | 71 | void SetupBottomEdgeNormally(block_s *block, unsigned int global_index_offset); 72 | void SetupRightEdgeNormally(block_s *block, unsigned int global_index_offset); 73 | void SetupTopEdgeNormally(block_s *block, unsigned int global_index_offset); 74 | void SetupLeftEdgeNormally(block_s *block, unsigned int global_index_offset); 75 | 76 | void SetupBottomEdgeFixGap(block_s *block, block_s *bottom_neighbor, unsigned int global_index_offset); 77 | void SetupRightEdgeFixGap(block_s *block, block_s *right_neighbor, unsigned int global_index_offset); 78 | void SetupTopEdgeFixGap(block_s *block, block_s *top_neighbor, unsigned int global_index_offset); 79 | void SetupLeftEdgeFixGap(block_s *block, block_s *left_neighbor, unsigned int global_index_offset); 80 | }; 81 | 82 | bool CheckTerrainSize(int x_size, int y_size); 83 | -------------------------------------------------------------------------------- /source/Main.cpp: -------------------------------------------------------------------------------- 1 | // Main.cpp 2 | 3 | #include "Precompiled.h" 4 | #include 5 | 6 | /* 7 | ================================================================================ 8 | Callback 9 | ================================================================================ 10 | */ 11 | 12 | static d3d11_ctx_s * gD3D11Ctx; 13 | static input_s gInputs[256]; 14 | static int gInputsCount; 15 | static Demo gDemo; 16 | 17 | static void OnReshape(int width, int height) { 18 | gDemo.Resize(width, height); 19 | } 20 | 21 | static void OnMouse(int button, int state, int x, int y) { 22 | if (gInputsCount < 256) { 23 | if (button == DX_LEFT_BUTTON) { 24 | input_s * input = gInputs + gInputsCount; 25 | input->mType = state == DX_DOWN ? IN_LBUTTON_DOWN : IN_LBUTTON_UP; 26 | input->mParam1 = x; 27 | input->mParam2 = y; 28 | gInputsCount++; 29 | } 30 | } 31 | } 32 | 33 | static void OnMotion(int x, int y) { 34 | if (gInputsCount < 256) { 35 | input_s * input = gInputs + gInputsCount; 36 | input->mType = IN_MOUSE_MOVE; 37 | input->mParam1 = x; 38 | input->mParam2 = y; 39 | gInputsCount++; 40 | } 41 | } 42 | 43 | static void OnKeyboard(int key) { 44 | if (gInputsCount < 256) { 45 | input_s * input = gInputs + gInputsCount; 46 | input->mType = IN_KEY_DOWN; 47 | input->mParam1 = key; 48 | gInputsCount++; 49 | } 50 | } 51 | 52 | static void OnKeyboardUp(int key) { 53 | if (gInputsCount < 256) { 54 | input_s * input = gInputs + gInputsCount; 55 | input->mType = IN_KEY_UP; 56 | input->mParam1 = key; 57 | gInputsCount++; 58 | } 59 | } 60 | 61 | static void OnIdle(int delta_ms) { 62 | gDemo.Frame(gInputs, gInputsCount, delta_ms * 0.001f); 63 | gInputsCount = 0; 64 | } 65 | 66 | static void OnClose() { 67 | gDemo.Shutdown(); 68 | } 69 | 70 | int main(int argc, char **argv) { 71 | #ifdef _DEBUG // detect memory leak 72 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 73 | #endif 74 | 75 | Sys_InitTimer(); 76 | 77 | printf("---------- GeoMipMapping ----------\n"); 78 | printf("F2: toggle draw terrain\n"); 79 | printf("F3: toggle draw wireframe mode\n"); 80 | printf("F4: toggle draw skydome\n"); 81 | printf("Space: hide/show cursor\n"); 82 | printf("W,S,A,D,Q,Z: to move around\n"); 83 | printf("Page Up: increase move speed (max: %d)\n", (int)MAX_MOVE_SPEED); 84 | printf("Page Down: decrease move speed (min: %d)\n", (int)MIN_MOVE_SPEED); 85 | printf("Arrow Up: increase pixel error (max: %d)\n", (int)MAX_PIXEL_ERROR); 86 | printf("Arrow Down: decrease pixel error (min: %d)\n\n", (int)MIN_PIXEL_ERROR); 87 | printf("Please select a test case (1: Grand Canyon (4K * 2k), 2: Puget Sound (4k * 4k): "); 88 | 89 | int user_input = 1; 90 | scanf_s("%d", &user_input); 91 | if (user_input < 1) { 92 | user_input = 1; 93 | } 94 | 95 | if (user_input > 2) { 96 | user_input = 2; 97 | } 98 | 99 | int test_case = user_input - 1; // convert to array index 100 | 101 | // extract res path 102 | char_t res_dir[MAX_PATH_]; 103 | 104 | #ifdef _UNICODE 105 | char_t exe_filename[MAX_PATH_]; 106 | Str_FrAnsi(argv[0], exe_filename, MAX_PATH_); 107 | Str_ExtractExeDir(exe_filename, res_dir, MAX_PATH_); 108 | #else 109 | Str_ExtractExeDir(argv[0], res_dir, MAX_PATH_); 110 | #endif 111 | Str_ExtractDirSelf(res_dir); 112 | Str_ExtractDirSelf(res_dir); 113 | Str_ExtractDirSelf(res_dir); 114 | Str_ExtractDirSelf(res_dir); 115 | strcat_s_(res_dir, TXT_("\\res")); 116 | 117 | if (!DX_CreateWindow(VIEWPORT_CX, VIEWPORT_CY, L"GeoMipMapping", &gD3D11Ctx)) { 118 | return 1; 119 | } 120 | 121 | printf("loading data ...\n"); 122 | 123 | if (!gDemo.Init(gD3D11Ctx, res_dir, test_case)) { 124 | gDemo.Shutdown(); 125 | 126 | gD3D11Ctx->mDeviceContext->Release(); 127 | gD3D11Ctx->mDevice->Release(); 128 | 129 | _getch(); // pause. display error message 130 | return 1; 131 | } 132 | 133 | printf("done.\n"); 134 | 135 | DX_ReshapeFunc(OnReshape); 136 | DX_MouseFunc(OnMouse); 137 | DX_MotionFunc(OnMotion); 138 | DX_KeyboardFunc(OnKeyboard); 139 | DX_KeyboardUpFunc(OnKeyboardUp); 140 | DX_IdleFunc(OnIdle); 141 | DX_CloseFunc(OnClose); 142 | 143 | DX_MainLoop(); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /source/Precompiled.cpp: -------------------------------------------------------------------------------- 1 | // Precompiled.cpp 2 | 3 | #include "Precompiled.h" 4 | -------------------------------------------------------------------------------- /source/Precompiled.h: -------------------------------------------------------------------------------- 1 | // Precompiled.h 2 | 3 | #pragma once 4 | 5 | // shared definition, functions 6 | #include "Shared.h" 7 | 8 | // tiny Direct3D framework 9 | #include "DXApp.h" 10 | 11 | // renderer 12 | #include "Renderer/Shaders.h" 13 | #include "Renderer/States.h" 14 | #include "Renderer/RenderShared.h" 15 | #include "Renderer/ConstantBuffers.h" 16 | #include "Renderer/RenderSkydome.h" 17 | #include "Renderer/RenderCloud.h" 18 | #include "Renderer/RenderTerrain.h" 19 | #include "Renderer/RenderText.h" 20 | #include "Renderer/Renderer.h" 21 | 22 | // key algorithm 23 | #include "GeoMipMapping.h" 24 | 25 | // demo 26 | #include "Viewer.h" 27 | #include "Terrain.h" 28 | #include "Demo.h" 29 | -------------------------------------------------------------------------------- /source/Renderer/ConstantBuffers.cpp: -------------------------------------------------------------------------------- 1 | // ConstantBuffers.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | ConstantBuffers 8 | ================================================================================ 9 | */ 10 | ConstantBuffers::ConstantBuffers() : 11 | mTextMVPBuffer(nullptr), 12 | mSkyMVPBuffer(nullptr), 13 | mSceneMVPBuffer(nullptr), 14 | mSceneMVBuffer(nullptr), 15 | mTexSizeBuffer(nullptr), 16 | mFogBuffer(nullptr), 17 | mCloudMoveBuffer(nullptr) 18 | { 19 | } 20 | 21 | ConstantBuffers::~ConstantBuffers() { 22 | // do nothing 23 | } 24 | 25 | bool ConstantBuffers::Init(d3d11_ctx_s *ctx) { 26 | if (!CreateConstantBuffer(ctx, sizeof(XMMATRIX), mTextMVPBuffer)) { 27 | return false; 28 | } 29 | 30 | if (!CreateConstantBuffer(ctx, sizeof(XMMATRIX), mSkyMVPBuffer)) { 31 | return false; 32 | } 33 | 34 | if (!CreateConstantBuffer(ctx, sizeof(XMMATRIX), mSceneMVPBuffer)) { 35 | return false; 36 | } 37 | 38 | if (!CreateConstantBuffer(ctx, sizeof(XMMATRIX), mSceneMVBuffer)) { 39 | return false; 40 | } 41 | 42 | if (!CreateConstantBuffer(ctx, sizeof(XMVECTOR), mTexSizeBuffer)) { 43 | return false; 44 | } 45 | 46 | if (!CreateConstantBuffer(ctx, sizeof(XMVECTOR), mFogBuffer)) { 47 | return false; 48 | } 49 | 50 | if (!CreateConstantBuffer(ctx, sizeof(XMVECTOR), mCloudMoveBuffer)) { 51 | return false; 52 | } 53 | 54 | return true; 55 | } 56 | 57 | void ConstantBuffers::Shutdown() { 58 | DX_SAFE_RELEASE(mCloudMoveBuffer); 59 | DX_SAFE_RELEASE(mFogBuffer); 60 | DX_SAFE_RELEASE(mTexSizeBuffer); 61 | DX_SAFE_RELEASE(mSceneMVBuffer); 62 | DX_SAFE_RELEASE(mSceneMVPBuffer); 63 | DX_SAFE_RELEASE(mSkyMVPBuffer); 64 | DX_SAFE_RELEASE(mTextMVPBuffer); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /source/Renderer/ConstantBuffers.h: -------------------------------------------------------------------------------- 1 | // ConstantBuffers.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | ConstantBuffers 8 | ================================================================================ 9 | */ 10 | class ConstantBuffers { 11 | public: 12 | 13 | ConstantBuffers(); 14 | ~ConstantBuffers(); 15 | 16 | bool Init(d3d11_ctx_s *ctx); 17 | void Shutdown(); 18 | 19 | public: 20 | 21 | ID3D11Buffer * mTextMVPBuffer; 22 | ID3D11Buffer * mSkyMVPBuffer; 23 | ID3D11Buffer * mSceneMVPBuffer; 24 | ID3D11Buffer * mSceneMVBuffer; 25 | ID3D11Buffer * mTexSizeBuffer; 26 | ID3D11Buffer * mFogBuffer; 27 | ID3D11Buffer * mCloudMoveBuffer; 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /source/Renderer/RenderCloud.cpp: -------------------------------------------------------------------------------- 1 | // RenderCloud.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | RenderCloud 8 | ================================================================================ 9 | */ 10 | RenderCloud::RenderCloud() : 11 | mVertexBuffer(nullptr), 12 | mIndexBuffer(nullptr), 13 | mTrianglesCount(0), 14 | mTexture(nullptr), 15 | mTextureSRV(nullptr), 16 | mTextureSS(nullptr) 17 | { 18 | } 19 | 20 | RenderCloud::~RenderCloud() { 21 | // do nothing 22 | } 23 | 24 | bool RenderCloud::Init(d3d11_ctx_s *ctx, const char_t *res_dir) { 25 | // load texture 26 | char_t full_tex_filename[MAX_PATH_]; 27 | sprintf_s_(full_tex_filename, TXT_("%s\\cloud\\cloud.png"), res_dir); 28 | int tex_width, tex_height; 29 | if (!LoadTexture(ctx, full_tex_filename, false, true, mTexture, mTextureSRV, mTextureSS, tex_width, tex_height)) { 30 | return false; 31 | } 32 | 33 | // setup geometry 34 | int vertices_count = 1 + SKYDOME_SLICES; 35 | mTrianglesCount = SKYDOME_SLICES; 36 | 37 | vertex_pos_clr_s * vert_buf = NEW__ vertex_pos_clr_s[vertices_count]; 38 | unsigned int * idx_buf = NEW__ unsigned int[mTrianglesCount * 3]; 39 | 40 | vertex_pos_clr_s * v = vert_buf; 41 | 42 | float fz = 2.0f; 43 | float radius = sqrtf(SKYDOME_RADIUS * SKYDOME_RADIUS - fz * fz); 44 | 45 | Vec3Set(v->mPosition, 0.0f, 0.0f, fz); 46 | Vec4Set(v->mColor, 0.5f, 0.5f, 0.0f, 0.2f); // r, g: texture coordinates, b: not used, a: alpha 47 | v++; 48 | 49 | float rad_step = (PI * 2.0f / (float)SKYDOME_SLICES); 50 | for (int i = 0; i < SKYDOME_SLICES; ++i) { 51 | float rad = i * rad_step; 52 | 53 | float fx = radius * sinf(rad); 54 | float fy = radius * cosf(rad); 55 | 56 | float t0 = (sinf(rad) + 1.0f) * 0.5f; 57 | float t1 = 1.0f - (cosf(rad) + 1.0f) * 0.5f; 58 | 59 | Vec3Set(v->mPosition, fx, fy, fz); 60 | Vec4Set(v->mColor, t0, t1, 0.0f, 0.0f); // alpha 0: cloud edge fade out 61 | v++; 62 | } 63 | 64 | // repeat cloud texture 65 | for (int i = 0; i < vertices_count; ++i) { 66 | vert_buf[i].mColor[0] *= 16.0f; 67 | vert_buf[i].mColor[1] *= 16.0f; 68 | } 69 | 70 | unsigned int * t = idx_buf; 71 | for (int i = 0; i < SKYDOME_SLICES; ++i) { 72 | t[0] = 0; 73 | t[1] = i + 1; 74 | t[2] = i + 2; 75 | 76 | if ((int)t[2] >= vertices_count) { 77 | t[2] = 1; 78 | } 79 | 80 | t += 3; 81 | } 82 | 83 | // create buffer objects 84 | if (!CreateVertexAndIndexBuffers(ctx, sizeof(vertex_pos_clr_s) * vertices_count, vert_buf, 85 | sizeof(unsigned int) * mTrianglesCount * 3, idx_buf, false, mVertexBuffer, mIndexBuffer)) { 86 | 87 | delete[]idx_buf; 88 | delete[]vert_buf; 89 | 90 | return false; 91 | } 92 | else { 93 | delete[]idx_buf; 94 | delete[]vert_buf; 95 | 96 | return true; 97 | } 98 | } 99 | 100 | void RenderCloud::Shutdown() { 101 | DX_SAFE_RELEASE(mIndexBuffer); 102 | DX_SAFE_RELEASE(mVertexBuffer); 103 | DX_SAFE_RELEASE(mTextureSS); 104 | DX_SAFE_RELEASE(mTextureSRV); 105 | DX_SAFE_RELEASE(mTexture); 106 | } 107 | 108 | void RenderCloud::Draw(ID3D11DeviceContext *ctx) { 109 | ctx->PSSetShaderResources(0, 1, &mTextureSRV); 110 | ctx->PSSetSamplers(0, 1, &mTextureSS); 111 | 112 | UINT stride = sizeof(vertex_pos_clr_s); 113 | UINT offset = 0; 114 | 115 | ctx->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset); 116 | ctx->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0); 117 | 118 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 119 | ctx->DrawIndexed(mTrianglesCount * 3, 0, 0); 120 | 121 | ctx->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr); 122 | ctx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, 0); 123 | 124 | ID3D11ShaderResourceView * null_srv_list[1] = { nullptr }; 125 | ID3D11SamplerState * null_ss_list[1] = { nullptr }; 126 | ctx->PSSetShaderResources(0, 1, null_srv_list); 127 | ctx->PSSetSamplers(0, 1, null_ss_list); 128 | } 129 | -------------------------------------------------------------------------------- /source/Renderer/RenderCloud.h: -------------------------------------------------------------------------------- 1 | // RenderCloud.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | RenderCloud 8 | ================================================================================ 9 | */ 10 | class RenderCloud { 11 | public: 12 | RenderCloud(); 13 | ~RenderCloud(); 14 | 15 | bool Init(d3d11_ctx_s *ctx, const char_t *res_dir); 16 | void Shutdown(); 17 | 18 | void Draw(ID3D11DeviceContext *ctx); 19 | 20 | private: 21 | 22 | ID3D11Buffer * mVertexBuffer; 23 | ID3D11Buffer * mIndexBuffer; 24 | int mTrianglesCount; 25 | 26 | ID3D11Texture2D * mTexture; 27 | ID3D11ShaderResourceView * mTextureSRV; 28 | ID3D11SamplerState * mTextureSS; 29 | }; 30 | -------------------------------------------------------------------------------- /source/Renderer/RenderShared.cpp: -------------------------------------------------------------------------------- 1 | // RenderShared.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | bool LoadTexture(d3d11_ctx_s *ctx, const char_t *file, bool point_filter, bool repeat, 6 | ID3D11Texture2D *&tex, ID3D11ShaderResourceView *&srv, ID3D11SamplerState *&ss, int &width, int &height) { 7 | image_s tex_data; 8 | if (ReadPNG(file, &tex_data)) { 9 | width = tex_data.mCX; 10 | height = tex_data.mCY; 11 | 12 | void * pixels = nullptr; 13 | bool free_pixels = false; 14 | if (tex_data.mFormat == IMG_FORMAT_1BYTE_RGB) { 15 | unsigned char * rgba = (unsigned char *)malloc(tex_data.mCX * tex_data.mCY * 4); 16 | pixels = rgba; 17 | free_pixels = true; 18 | 19 | const unsigned char * rgb = (const unsigned char *)tex_data.mData; 20 | for (int y = 0; y < tex_data.mCY; ++y) { 21 | const unsigned char * src_line = rgb + y * tex_data.mCX * 3; 22 | unsigned char * dst_line = rgba + y * tex_data.mCX * 4; 23 | for (int x = 0; x < tex_data.mCX; ++x) { 24 | const unsigned char * src_pixel = src_line + x * 3; 25 | unsigned char * dst_pixel = dst_line + x * 4; 26 | dst_pixel[0] = src_pixel[0]; 27 | dst_pixel[1] = src_pixel[1]; 28 | dst_pixel[2] = src_pixel[2]; 29 | dst_pixel[3] = 255; 30 | } 31 | } 32 | } 33 | else if (tex_data.mFormat == IMG_FORMAT_1BYTE_RGBA) { 34 | pixels = tex_data.mData; 35 | } 36 | else { 37 | FreeImg(&tex_data); 38 | return false; 39 | } 40 | 41 | D3D11_TEXTURE2D_DESC td; 42 | memset(&td, 0, sizeof(td)); 43 | 44 | td.Width = tex_data.mCX; 45 | td.Height = tex_data.mCY; 46 | td.MipLevels = 1; // no existing mip-map 47 | td.ArraySize = 1; 48 | td.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 49 | td.SampleDesc.Count = 1; 50 | td.SampleDesc.Quality = 0; 51 | td.Usage = D3D11_USAGE_DEFAULT; 52 | td.BindFlags = D3D11_BIND_SHADER_RESOURCE; 53 | td.CPUAccessFlags = 0; // no CPU access 54 | td.MiscFlags = 0; 55 | 56 | D3D11_SUBRESOURCE_DATA data; 57 | 58 | data.pSysMem = pixels; 59 | data.SysMemPitch = tex_data.mCX * 4; 60 | data.SysMemSlicePitch = tex_data.mCX * tex_data.mCY * 4; 61 | 62 | if (DX_FAILED(ctx->mDevice->CreateTexture2D(&td, &data, &tex))) { 63 | 64 | if (free_pixels) { 65 | free(pixels); 66 | } 67 | 68 | FreeImg(&tex_data); 69 | return false; 70 | } 71 | 72 | if (free_pixels) { 73 | free(pixels); 74 | } 75 | FreeImg(&tex_data); 76 | 77 | // create shader resource view 78 | D3D11_SHADER_RESOURCE_VIEW_DESC vd; 79 | 80 | memset(&vd, 0, sizeof(vd)); 81 | 82 | vd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 83 | vd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 84 | vd.Texture2D.MipLevels = 1; 85 | 86 | if (DX_FAILED(ctx->mDevice->CreateShaderResourceView(tex, &vd, &srv))) { 87 | return false; 88 | } 89 | 90 | // create sample state 91 | D3D11_SAMPLER_DESC sd; 92 | 93 | sd.Filter = point_filter ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; 94 | sd.AddressU = repeat ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; 95 | sd.AddressV = repeat ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; 96 | sd.AddressW = repeat ? D3D11_TEXTURE_ADDRESS_WRAP : D3D11_TEXTURE_ADDRESS_CLAMP; 97 | sd.MipLODBias = 0.0f; 98 | sd.MaxAnisotropy = 1; 99 | sd.ComparisonFunc = D3D11_COMPARISON_NEVER; 100 | sd.BorderColor[0] = sd.BorderColor[1] = sd.BorderColor[2] = sd.BorderColor[3] = 1.0f; 101 | sd.MinLOD = 0; 102 | sd.MaxLOD = D3D11_FLOAT32_MAX; 103 | 104 | if (DX_FAILED(ctx->mDevice->CreateSamplerState(&sd, &ss))) { 105 | return false; 106 | } 107 | 108 | return true; 109 | } 110 | else { 111 | return false; 112 | } 113 | } 114 | 115 | bool CreateConstantBuffer(d3d11_ctx_s *ctx, size_t size, ID3D11Buffer *&buffer) { 116 | D3D11_BUFFER_DESC desc; 117 | 118 | desc.ByteWidth = (UINT)size; 119 | desc.Usage = D3D11_USAGE_DYNAMIC; 120 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 121 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 122 | desc.MiscFlags = 0; 123 | desc.StructureByteStride = 0; 124 | 125 | if (DX_FAILED(ctx->mDevice->CreateBuffer(&desc, nullptr, &buffer))) { 126 | return false; 127 | } 128 | 129 | return true; 130 | } 131 | 132 | void SetConstantBuffer(d3d11_ctx_s *ctx, ID3D11Buffer *buffer, const void *data, size_t size) { 133 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 134 | if (!DX_FAILED(ctx->mDeviceContext->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource))) { 135 | memcpy(mapped_resource.pData, data, size); 136 | ctx->mDeviceContext->Unmap(buffer, 0); 137 | } 138 | } 139 | 140 | bool CreateBuffer(d3d11_ctx_s *ctx, unsigned int type, unsigned int size, const void * buf_data, bool CPU_access_write, ID3D11Buffer *&b) { 141 | D3D11_BUFFER_DESC desc; 142 | D3D11_SUBRESOURCE_DATA rd; 143 | 144 | desc.ByteWidth = size; 145 | desc.Usage = CPU_access_write ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; 146 | desc.BindFlags = type; 147 | desc.CPUAccessFlags = CPU_access_write ? D3D11_CPU_ACCESS_WRITE : 0; 148 | desc.MiscFlags = 0; 149 | desc.StructureByteStride = 0; 150 | 151 | if (buf_data) { 152 | rd.pSysMem = buf_data; 153 | rd.SysMemPitch = 0; 154 | rd.SysMemSlicePitch = 0; 155 | 156 | if (DX_FAILED(ctx->mDevice->CreateBuffer(&desc, &rd, &b))) { 157 | return false; 158 | } 159 | } 160 | else { 161 | if (DX_FAILED(ctx->mDevice->CreateBuffer(&desc, nullptr, &b))) { 162 | return false; 163 | } 164 | } 165 | 166 | return true; 167 | } 168 | 169 | bool CreateVertexAndIndexBuffers(d3d11_ctx_s *ctx, unsigned int vb_size, const void * vb_buf, unsigned int ib_size, const void * ib_buf, bool CPU_access_write, 170 | ID3D11Buffer *&vb, ID3D11Buffer *&ib) { 171 | 172 | return CreateBuffer(ctx, D3D11_BIND_VERTEX_BUFFER, vb_size, vb_buf, CPU_access_write, vb) 173 | && CreateBuffer(ctx, D3D11_BIND_INDEX_BUFFER, ib_size, ib_buf, CPU_access_write, ib); 174 | } 175 | 176 | // shaders 177 | static const int STACK_BUFFER_SIZE = 65536; 178 | 179 | bool CreateVertexShaderAndInputLayout(ID3D11Device * device, const char_t *filename, 180 | const D3D11_INPUT_ELEMENT_DESC *desc, UINT desc_count, ID3D11VertexShader *&shader, ID3D11InputLayout *&layout) { 181 | char buffer[STACK_BUFFER_SIZE]; 182 | int size = File_LoadBinary(filename, buffer, STACK_BUFFER_SIZE); 183 | if (size <= 0) { 184 | return false; 185 | } 186 | 187 | if (DX_FAILED(device->CreateVertexShader(buffer, size, nullptr, &shader))) { 188 | return false; 189 | } 190 | 191 | if (DX_FAILED(device->CreateInputLayout(desc, desc_count, buffer, size, &layout))) { 192 | return false; 193 | } 194 | 195 | return true; 196 | } 197 | 198 | bool CreatePixelShader(ID3D11Device * device, const char_t *filename, ID3D11PixelShader *&shader) { 199 | char buffer[STACK_BUFFER_SIZE]; 200 | int size = File_LoadBinary(filename, buffer, STACK_BUFFER_SIZE); 201 | if (size <= 0) { 202 | return false; 203 | } 204 | 205 | if (DX_FAILED(device->CreatePixelShader(buffer, size, nullptr, &shader))) { 206 | return false; 207 | } 208 | 209 | return true; 210 | } 211 | -------------------------------------------------------------------------------- /source/Renderer/RenderShared.h: -------------------------------------------------------------------------------- 1 | // RenderShared.h 2 | 3 | #pragma once 4 | 5 | // sky dome 6 | #define ZENITH_COLOR { 0.1f, 0.5f, 0.9f, 1.0f } 7 | #define HORIZONTAL_COLOR { 0.8f, 0.9f, 0.9f, 1.0f } 8 | 9 | #define SKYDOME_SLICES 20 10 | #define SKYDOME_STACKS 15 11 | #define SKYDOME_RADIUS 64.0f 12 | 13 | // fog 14 | #define FOG_DENSITY 0.002f 15 | 16 | 17 | // texture 18 | bool LoadTexture(d3d11_ctx_s *ctx, const char_t *file, bool point_filter, bool repeat, 19 | ID3D11Texture2D *&tex, ID3D11ShaderResourceView *&srv, ID3D11SamplerState *&ss, int &width, int &height); 20 | 21 | // buffers 22 | bool CreateConstantBuffer(d3d11_ctx_s *ctx, size_t size, ID3D11Buffer *&buffer); 23 | void SetConstantBuffer(d3d11_ctx_s *ctx, ID3D11Buffer *buffer, const void *data, size_t size); 24 | 25 | bool CreateBuffer(d3d11_ctx_s *ctx, unsigned int type, unsigned int size, const void * buf_data, bool CPU_access_write, ID3D11Buffer *&b); 26 | bool CreateVertexAndIndexBuffers(d3d11_ctx_s *ctx, unsigned int vb_size, const void * vb_buf, unsigned int ib_size, const void * ib_buf, bool CPU_access_write, 27 | ID3D11Buffer *&vb, ID3D11Buffer *&ib); 28 | 29 | // shaders 30 | bool CreateVertexShaderAndInputLayout(ID3D11Device * device, 31 | const char_t *filename, const D3D11_INPUT_ELEMENT_DESC *desc, UINT desc_count, ID3D11VertexShader *&shader, ID3D11InputLayout *&layout); 32 | bool CreatePixelShader(ID3D11Device * device, const char_t *filename, ID3D11PixelShader *&shader); 33 | -------------------------------------------------------------------------------- /source/Renderer/RenderSkydome.cpp: -------------------------------------------------------------------------------- 1 | // RenderSkydome.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | RenderSkydome 8 | ================================================================================ 9 | */ 10 | RenderSkydome::RenderSkydome() : 11 | mVertexBuffer(nullptr), 12 | mIndexBuffer(nullptr), 13 | mTrianglesCount(0) 14 | { 15 | } 16 | 17 | RenderSkydome::~RenderSkydome() { 18 | // do nothing 19 | } 20 | 21 | bool RenderSkydome::Init(d3d11_ctx_s *ctx) { 22 | int vertices_count = 1 + (SKYDOME_STACKS + 1) * SKYDOME_SLICES; 23 | mTrianglesCount = SKYDOME_SLICES + SKYDOME_STACKS * SKYDOME_SLICES * 2; 24 | 25 | vertex_pos_clr_s * vert_buf = NEW__ vertex_pos_clr_s[vertices_count]; 26 | unsigned int * idx_buf = NEW__ unsigned int[mTrianglesCount * 3]; 27 | 28 | vertex_pos_clr_s * v = vert_buf; 29 | unsigned int * i = idx_buf; 30 | 31 | float radius = SKYDOME_RADIUS; 32 | vec4_t zenith_color = ZENITH_COLOR; 33 | vec4_t horizontal_color = HORIZONTAL_COLOR; 34 | vec4_t color_delta; 35 | Vec4Sub(horizontal_color, zenith_color, color_delta); 36 | 37 | Vec3Set(v->mPosition, 0.0f, 0.0f, radius); 38 | Vec4Copy(zenith_color, v->mColor); 39 | 40 | float half_rad = Deg2Rad(90.0f); 41 | float stack_step = half_rad / (float)SKYDOME_STACKS; 42 | float slice_step = PI * 2.0f / (float)SKYDOME_SLICES; 43 | 44 | for (int stack = 0; stack <= SKYDOME_STACKS; ++stack) { 45 | float stack_angle = (stack + 1) * stack_step; 46 | 47 | float z = radius * cosf(stack_angle); 48 | float stack_radius = radius * sinf(stack_angle); 49 | 50 | if (stack == SKYDOME_STACKS) { // the last stack 51 | z = -radius * 0.5f; 52 | stack_radius = radius; 53 | } 54 | 55 | for (int slice = 0; slice < SKYDOME_SLICES; ++slice) { 56 | float slice_angle = slice * slice_step; 57 | 58 | float x = stack_radius * cosf(slice_angle); 59 | float y = stack_radius * sinf(slice_angle); 60 | 61 | v++; 62 | 63 | float factor = 1.0f; 64 | if (stack < SKYDOME_STACKS) { 65 | float persent = ((float)stack + 1.0f) / (float)SKYDOME_STACKS; 66 | factor = powf(persent, 2.0f); // as exponential increase 67 | } 68 | 69 | Vec3Set(v->mPosition, x, y, z); 70 | Vec4MulAdd(color_delta, factor, zenith_color, v->mColor); 71 | 72 | if (0 == stack) {// triangle fan 73 | i[0] = 0; 74 | i[1] = 1 + (slice + 1) % SKYDOME_SLICES; 75 | i[2] = 1 + slice; 76 | 77 | i += 3; 78 | } 79 | else { // triangle strip 80 | /* indices 81 | 82 | zenith 83 | / \ 84 | 0---3 85 | | \ | 86 | 1---2 87 | */ 88 | 89 | int idx0 = 1 /* first zenith vertex */ + (stack - 1) * SKYDOME_SLICES /* stack offset */ + slice /* current slice */; 90 | int idx1 = 1 + stack * SKYDOME_SLICES + slice; 91 | int idx2 = 1 + stack * SKYDOME_SLICES + (slice + 1) % SKYDOME_SLICES; 92 | int idx3 = 1 + (stack - 1) * SKYDOME_SLICES + (slice + 1) % SKYDOME_SLICES; 93 | 94 | i[0] = idx0; 95 | i[1] = idx2; 96 | i[2] = idx1; 97 | i[3] = idx0; 98 | i[4] = idx3; 99 | i[5] = idx2; 100 | 101 | i += 6; 102 | } 103 | } 104 | } 105 | 106 | // create buffer objects 107 | if (!CreateVertexAndIndexBuffers(ctx, sizeof(vertex_pos_clr_s) * vertices_count, vert_buf, 108 | sizeof(unsigned int) * mTrianglesCount * 3, idx_buf, false, mVertexBuffer, mIndexBuffer)) { 109 | 110 | delete[]idx_buf; 111 | delete[]vert_buf; 112 | 113 | return false; 114 | } 115 | else { 116 | delete[]idx_buf; 117 | delete[]vert_buf; 118 | 119 | return true; 120 | } 121 | } 122 | 123 | void RenderSkydome::Shutdown() { 124 | DX_SAFE_RELEASE(mIndexBuffer); 125 | DX_SAFE_RELEASE(mVertexBuffer); 126 | } 127 | 128 | void RenderSkydome::Draw(ID3D11DeviceContext *ctx) { 129 | UINT stride = sizeof(vertex_pos_clr_s); 130 | UINT offset = 0; 131 | 132 | ctx->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset); 133 | ctx->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0); 134 | 135 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 136 | ctx->DrawIndexed(mTrianglesCount * 3, 0, 0); 137 | 138 | ctx->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr); 139 | ctx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, 0); 140 | } 141 | -------------------------------------------------------------------------------- /source/Renderer/RenderSkydome.h: -------------------------------------------------------------------------------- 1 | // RenderSkydome.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | RenderSkydome 8 | ================================================================================ 9 | */ 10 | class RenderSkydome { 11 | public: 12 | RenderSkydome(); 13 | ~RenderSkydome(); 14 | 15 | bool Init(d3d11_ctx_s *ctx); 16 | void Shutdown(); 17 | 18 | void Draw(ID3D11DeviceContext *ctx); 19 | 20 | private: 21 | 22 | ID3D11Buffer * mVertexBuffer; 23 | ID3D11Buffer * mIndexBuffer; 24 | int mTrianglesCount; 25 | }; 26 | -------------------------------------------------------------------------------- /source/Renderer/RenderTerrain.cpp: -------------------------------------------------------------------------------- 1 | // RenderTerrain.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | RenderTerrain 8 | ================================================================================ 9 | */ 10 | RenderTerrain::RenderTerrain() : 11 | mVertexBuffer(nullptr), 12 | mVerticesCount(0), 13 | mIndexBuffer(nullptr), 14 | mIndicesCount(0), 15 | mDiffuseTexture(nullptr), 16 | mDiffuseTextureSRV(nullptr), 17 | mDiffuseTextureSS(nullptr), 18 | mDetailTexture(nullptr), 19 | mDetailTextureSRV(nullptr), 20 | mDetailTextureSS(nullptr), 21 | mTriangleCount(0), 22 | mTexWidth(1), 23 | mTexHeight(1) 24 | { 25 | } 26 | 27 | RenderTerrain::~RenderTerrain() { 28 | // do nothing 29 | } 30 | 31 | bool RenderTerrain::Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case) { 32 | if (!CreateVertexAndIndexBuffers(ctx, sizeof(vertex_pos_s) * MAX_DRAW_VERT_COUNT, nullptr, 33 | sizeof(unsigned int) * MAX_DRAW_IDX_COUNT, nullptr, true, mVertexBuffer, mIndexBuffer)) { 34 | return false; 35 | } 36 | 37 | // load base texture 38 | char_t full_tex_filename[MAX_PATH_]; 39 | sprintf_s_(full_tex_filename, TXT_("%s\\terrain\\%s"), res_dir, TEST_DATA[test_case].mColorMap); 40 | 41 | if (!LoadTexture(ctx, full_tex_filename, false, true, mDiffuseTexture, mDiffuseTextureSRV, mDiffuseTextureSS, mTexWidth, mTexHeight)) { 42 | return false; 43 | } 44 | 45 | // load detail texture 46 | sprintf_s_(full_tex_filename, TXT_("%s\\terrain\\detail.png"), res_dir); 47 | 48 | int detail_width, detail_height; 49 | if (!LoadTexture(ctx, full_tex_filename, false, true, mDetailTexture, mDetailTextureSRV, mDetailTextureSS, detail_width, detail_height)) { 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | 56 | void RenderTerrain::Shutdown() { 57 | DX_SAFE_RELEASE(mDetailTextureSS); 58 | DX_SAFE_RELEASE(mDetailTextureSRV); 59 | DX_SAFE_RELEASE(mDetailTexture); 60 | DX_SAFE_RELEASE(mDiffuseTextureSS); 61 | DX_SAFE_RELEASE(mDiffuseTextureSRV); 62 | DX_SAFE_RELEASE(mDiffuseTexture); 63 | DX_SAFE_RELEASE(mIndexBuffer); 64 | DX_SAFE_RELEASE(mVertexBuffer); 65 | } 66 | 67 | int RenderTerrain::GetTexWidth() const { 68 | return mTexWidth; 69 | } 70 | 71 | int RenderTerrain::GetTexHeight() const { 72 | return mTexHeight; 73 | } 74 | 75 | void RenderTerrain::Update(ID3D11DeviceContext *ctx, const mesh_s &mesh) { 76 | mTriangleCount = mesh.mTriangleCount; 77 | 78 | D3D11_MAPPED_SUBRESOURCE ms; 79 | 80 | if (!DX_FAILED(ctx->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms))) { 81 | memcpy(ms.pData, mesh.mVertices, sizeof(vertex_pos_s) * mesh.mVerticesCount); 82 | mVerticesCount = mesh.mVerticesCount; 83 | ctx->Unmap(mVertexBuffer, 0); 84 | } 85 | 86 | if (!DX_FAILED(ctx->Map(mIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms))) { 87 | memcpy(ms.pData, mesh.mIndices, sizeof(unsigned int) * mesh.mIndicesCount); 88 | mIndicesCount = mesh.mIndicesCount; 89 | ctx->Unmap(mIndexBuffer, 0); 90 | } 91 | } 92 | 93 | void RenderTerrain::Draw(ID3D11DeviceContext *ctx, bool solid) { 94 | if (mIndicesCount > 0) { 95 | if (solid) { 96 | ctx->PSSetShaderResources(0, 1, &mDiffuseTextureSRV); 97 | ctx->PSSetSamplers(0, 1, &mDiffuseTextureSS); 98 | ctx->PSSetShaderResources(1, 1, &mDetailTextureSRV); 99 | ctx->PSSetSamplers(1, 1, &mDetailTextureSS); 100 | } 101 | 102 | UINT stride = sizeof(vertex_pos_s); 103 | UINT offset = 0; 104 | ctx->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset); 105 | ctx->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0); 106 | 107 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 108 | ctx->DrawIndexed(mIndicesCount, 0, 0); 109 | 110 | ctx->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr); 111 | ctx->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, 0); 112 | 113 | if (solid) { 114 | ID3D11ShaderResourceView * null_srv_list[1] = { nullptr }; 115 | ID3D11SamplerState * null_ss_list[1] = { nullptr }; 116 | ctx->PSSetShaderResources(0, 1, null_srv_list); 117 | ctx->PSSetSamplers(0, 1, null_ss_list); 118 | ctx->PSSetShaderResources(1, 1, null_srv_list); 119 | ctx->PSSetSamplers(1, 1, null_ss_list); 120 | } 121 | } 122 | } 123 | 124 | int RenderTerrain::GetTriangleCount() const { 125 | return mTriangleCount; 126 | } 127 | -------------------------------------------------------------------------------- /source/Renderer/RenderTerrain.h: -------------------------------------------------------------------------------- 1 | // RenderTerrain.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | RenderTerrain 8 | ================================================================================ 9 | */ 10 | class RenderTerrain { 11 | public: 12 | RenderTerrain(); 13 | ~RenderTerrain(); 14 | 15 | bool Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case); 16 | void Shutdown(); 17 | 18 | int GetTexWidth() const; 19 | int GetTexHeight() const; 20 | 21 | void Update(ID3D11DeviceContext *ctx, const mesh_s &mesh); 22 | void Draw(ID3D11DeviceContext *ctx, bool solid); 23 | 24 | int GetTriangleCount() const; 25 | 26 | private: 27 | 28 | ID3D11Buffer * mVertexBuffer; 29 | UINT mVerticesCount; 30 | 31 | ID3D11Buffer * mIndexBuffer; 32 | UINT mIndicesCount; 33 | 34 | ID3D11Texture2D * mDiffuseTexture; 35 | ID3D11ShaderResourceView * mDiffuseTextureSRV; 36 | ID3D11SamplerState * mDiffuseTextureSS; 37 | 38 | ID3D11Texture2D * mDetailTexture; 39 | ID3D11ShaderResourceView * mDetailTextureSRV; 40 | ID3D11SamplerState * mDetailTextureSS; 41 | 42 | int mTriangleCount; 43 | 44 | int mTexWidth; 45 | int mTexHeight; 46 | 47 | void Destroy(); 48 | }; 49 | -------------------------------------------------------------------------------- /source/Renderer/RenderText.cpp: -------------------------------------------------------------------------------- 1 | // RenderText.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | RenderText 8 | ================================================================================ 9 | */ 10 | RenderText::RenderText() : 11 | mVertexBuffer(nullptr), 12 | mVerticesCount(0), 13 | mFontTexture(nullptr), 14 | mFontTextureSRV(nullptr), 15 | mFontTextureSS(nullptr) 16 | { 17 | } 18 | 19 | RenderText::~RenderText() { 20 | // do nothing 21 | } 22 | 23 | bool RenderText::Init(d3d11_ctx_s *ctx, const char_t *res_dir) { 24 | // init texture coordinates 25 | int count = 0; 26 | for (float y = 128.0f; y > 16.0f; y -= 16.0f) { 27 | for (float x = 0.0f; x < 112.0f; x += 8.0f) { 28 | mCharInfos[count].mS0 = x / 128.0f; 29 | mCharInfos[count].mT0 = 1.0f - ((y - 16.0f) / 128.0f); 30 | mCharInfos[count].mS1 = (x + 8.0f) / 128.0f; 31 | mCharInfos[count].mT1 = 1.0f - (y / 128.0f); 32 | count++; 33 | if (count >= 95) { 34 | break; 35 | } 36 | } 37 | 38 | if (count >= 95) { 39 | break; 40 | } 41 | } 42 | 43 | // vertex buffer 44 | if (!CreateBuffer(ctx, D3D11_BIND_VERTEX_BUFFER, sizeof(vertex_pos_texcoord_s) * MAX_PRINT_TEXT_LEN * 6, nullptr, true, mVertexBuffer)) { 45 | return false; 46 | } 47 | 48 | // font texture 49 | char_t full_tex_filename[MAX_PATH_]; 50 | sprintf_s_(full_tex_filename, TXT_("%s\\font\\font.png"), res_dir); 51 | 52 | int tex_width, tex_height; // dummy 53 | return LoadTexture(ctx, full_tex_filename, true, false, mFontTexture, mFontTextureSRV, mFontTextureSS, tex_width, tex_height); 54 | } 55 | 56 | void RenderText::Shutdown() { 57 | DX_SAFE_RELEASE(mFontTextureSS); 58 | DX_SAFE_RELEASE(mFontTextureSRV); 59 | DX_SAFE_RELEASE(mFontTexture); 60 | DX_SAFE_RELEASE(mVertexBuffer); 61 | } 62 | 63 | void RenderText::Print(ID3D11DeviceContext *ctx, const char *text) { 64 | #define TEXT_CX 8.0f 65 | #define TEXT_CY 16.0f 66 | 67 | D3D11_MAPPED_SUBRESOURCE ms; 68 | 69 | if (!DX_FAILED(ctx->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms))) { 70 | vertex_pos_texcoord_s * v = (vertex_pos_texcoord_s*)ms.pData; 71 | mVerticesCount = 0; 72 | 73 | float x = 0.0f; 74 | float y = 0.0f; 75 | const char * pc = text; 76 | while (*pc) { 77 | if (mVerticesCount >= MAX_PRINT_TEXT_LEN * 6) { 78 | break; // truncate 79 | } 80 | 81 | mVerticesCount += 6; 82 | char c = *pc; 83 | 84 | // clamp char 85 | if (c < 32) { 86 | c = 32; 87 | } 88 | 89 | int index = c - 32; 90 | 91 | if (index >= 95) { 92 | index = 0; 93 | } 94 | 95 | char_info_s * tex_coord = mCharInfos + index; 96 | 97 | v[0].mPosition[0] = x; 98 | v[0].mPosition[1] = y; 99 | v[0].mPosition[2] = 0.0f; 100 | v[0].mTexCoord[0] = tex_coord->mS0; 101 | v[0].mTexCoord[1] = tex_coord->mT0; 102 | 103 | v[1].mPosition[0] = x + TEXT_CX; 104 | v[1].mPosition[1] = y; 105 | v[1].mPosition[2] = 0.0f; 106 | v[1].mTexCoord[0] = tex_coord->mS1; 107 | v[1].mTexCoord[1] = tex_coord->mT0; 108 | 109 | v[2].mPosition[0] = x; 110 | v[2].mPosition[1] = y + TEXT_CY; 111 | v[2].mPosition[2] = 0.0f; 112 | v[2].mTexCoord[0] = tex_coord->mS0; 113 | v[2].mTexCoord[1] = tex_coord->mT1; 114 | 115 | v[3].mPosition[0] = x + TEXT_CX; 116 | v[3].mPosition[1] = y + TEXT_CY; 117 | v[3].mPosition[2] = 0.0f; 118 | v[3].mTexCoord[0] = tex_coord->mS1; 119 | v[3].mTexCoord[1] = tex_coord->mT1; 120 | 121 | v[4].mPosition[0] = x; 122 | v[4].mPosition[1] = y + TEXT_CY; 123 | v[4].mPosition[2] = 0.0f; 124 | v[4].mTexCoord[0] = tex_coord->mS0; 125 | v[4].mTexCoord[1] = tex_coord->mT1; 126 | 127 | v[5].mPosition[0] = x + TEXT_CX; 128 | v[5].mPosition[1] = y; 129 | v[5].mPosition[2] = 0.0f; 130 | v[5].mTexCoord[0] = tex_coord->mS1; 131 | v[5].mTexCoord[1] = tex_coord->mT0; 132 | 133 | x += TEXT_CX; 134 | v += 6; 135 | 136 | pc++; 137 | } 138 | 139 | ctx->Unmap(mVertexBuffer, 0); 140 | } 141 | } 142 | 143 | void RenderText::Draw(ID3D11DeviceContext *ctx) { 144 | if (mVerticesCount) { 145 | ctx->PSSetShaderResources(0, 1, &mFontTextureSRV); 146 | ctx->PSSetSamplers(0, 1, &mFontTextureSS); 147 | 148 | UINT stride = sizeof(vertex_pos_texcoord_s); 149 | UINT offset = 0; 150 | ctx->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset); 151 | 152 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 153 | ctx->Draw(mVerticesCount, 0); 154 | 155 | ctx->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr); 156 | 157 | ID3D11ShaderResourceView * null_srv_list[1] = { nullptr }; 158 | ID3D11SamplerState * null_ss_list[1] = { nullptr }; 159 | ctx->PSSetShaderResources(0, 1, null_srv_list); 160 | ctx->PSSetSamplers(0, 1, null_ss_list); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /source/Renderer/RenderText.h: -------------------------------------------------------------------------------- 1 | // RenderText.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | RenderText 8 | ================================================================================ 9 | */ 10 | class RenderText { 11 | public: 12 | RenderText(); 13 | ~RenderText(); 14 | 15 | bool Init(d3d11_ctx_s *ctx, const char_t *res_dir); 16 | void Shutdown(); 17 | 18 | void Print(ID3D11DeviceContext *ctx, const char *text); 19 | 20 | void Draw(ID3D11DeviceContext *ctx); 21 | 22 | private: 23 | 24 | // texture coordinate 25 | struct char_info_s { 26 | float mS0; 27 | float mT0; 28 | float mS1; 29 | float mT1; 30 | }; 31 | 32 | char_info_s mCharInfos[95]; 33 | 34 | ID3D11Buffer * mVertexBuffer; 35 | UINT mVerticesCount; 36 | 37 | ID3D11Texture2D * mFontTexture; 38 | ID3D11ShaderResourceView * mFontTextureSRV; 39 | ID3D11SamplerState * mFontTextureSS; 40 | }; 41 | -------------------------------------------------------------------------------- /source/Renderer/Renderer.cpp: -------------------------------------------------------------------------------- 1 | // Renderer.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | Renderer 8 | ================================================================================ 9 | */ 10 | static const float BLEND_FACTORS[4] = { 0.0f }; 11 | 12 | Renderer::Renderer() : 13 | mCtx(nullptr), 14 | mDXGISwapChain(nullptr), 15 | mDefaultRenderTargetView(nullptr), 16 | mDefaultDepthStencilTexture2D(nullptr), 17 | mDefaultDepthStencilView(nullptr), 18 | mViewCX(1), 19 | mViewCY(1) 20 | { 21 | mCloudMove[0] = mCloudMove[1] = 0.0f; 22 | } 23 | 24 | Renderer::~Renderer() { 25 | // do nothing 26 | } 27 | 28 | bool Renderer::Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case) { 29 | mCtx = ctx; 30 | 31 | if (!Reshape(VIEWPORT_CX, VIEWPORT_CY)) { 32 | return false; 33 | } 34 | 35 | 36 | if (!mStates.Init(ctx)) { 37 | return false; 38 | } 39 | 40 | if (!mCBuffers.Init(ctx)) { 41 | return false; 42 | } 43 | 44 | char_t shader_dir[MAX_PATH_]; 45 | sprintf_s_(shader_dir, TXT_("%s\\shaders"), res_dir); 46 | if (!mShaders.Init(ctx, shader_dir)) { 47 | return false; 48 | } 49 | 50 | if (!mText.Init(ctx, res_dir)) { 51 | return false; 52 | } 53 | 54 | if (!mSkydome.Init(ctx)) { 55 | return false; 56 | } 57 | 58 | if (!mCloud.Init(ctx, res_dir)) { 59 | return false; 60 | } 61 | 62 | if (!mTerrain.Init(ctx, res_dir, test_case)) { 63 | return false; 64 | } 65 | 66 | return true; 67 | } 68 | 69 | void Renderer::Shutdown() { 70 | mTerrain.Shutdown(); 71 | mCloud.Shutdown(); 72 | mSkydome.Shutdown(); 73 | mText.Shutdown(); 74 | mShaders.Shutdown(); 75 | mCBuffers.Shutdown(); 76 | mStates.Shutdown(); 77 | 78 | DX_SAFE_RELEASE(mDefaultDepthStencilView); 79 | DX_SAFE_RELEASE(mDefaultDepthStencilTexture2D); 80 | DX_SAFE_RELEASE(mDefaultRenderTargetView); 81 | DX_SAFE_RELEASE(mDXGISwapChain); 82 | } 83 | 84 | bool Renderer::Reshape(int view_width, int view_height) { 85 | if (view_width < 1) { 86 | view_width = 1; 87 | } 88 | 89 | if (view_height < 1) { 90 | view_height = 1; 91 | } 92 | 93 | mViewCX = view_width; 94 | mViewCY = view_height; 95 | 96 | DX_SAFE_RELEASE(mDefaultDepthStencilView); 97 | DX_SAFE_RELEASE(mDefaultDepthStencilTexture2D); 98 | DX_SAFE_RELEASE(mDefaultRenderTargetView); 99 | DX_SAFE_RELEASE(mDXGISwapChain); 100 | 101 | // describe the swap chain 102 | DXGI_SWAP_CHAIN_DESC scd; 103 | 104 | scd.BufferDesc.Width = view_width; 105 | scd.BufferDesc.Height = view_height; 106 | scd.BufferDesc.RefreshRate.Numerator = 60; 107 | scd.BufferDesc.RefreshRate.Denominator = 1; 108 | scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 109 | scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 110 | scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 111 | 112 | scd.SampleDesc.Count = 1; 113 | scd.SampleDesc.Quality = 0; 114 | 115 | scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 116 | scd.BufferCount = 1; // one back buffer 117 | scd.OutputWindow = mCtx->mWnd; 118 | scd.Windowed = true; 119 | scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 120 | scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 121 | 122 | if (!DX_CreateSwapChain(&scd, &mDXGISwapChain)) { 123 | return false; 124 | } 125 | 126 | // create the render target view 127 | if (!DX_CreateRenderTargetView(mDXGISwapChain, &mDefaultRenderTargetView)) { 128 | return false; 129 | } 130 | 131 | // create the depth / stencil buffer and view 132 | D3D11_TEXTURE2D_DESC depthStencilDesc; 133 | depthStencilDesc.Width = view_width; 134 | depthStencilDesc.Height = view_height; 135 | depthStencilDesc.MipLevels = 1; 136 | depthStencilDesc.ArraySize = 1; 137 | depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 138 | 139 | // must match swap chain MSAAA values 140 | depthStencilDesc.SampleDesc.Count = 1; 141 | depthStencilDesc.SampleDesc.Quality = 0; 142 | depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; 143 | depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; 144 | depthStencilDesc.CPUAccessFlags = 0; 145 | depthStencilDesc.MiscFlags = 0; 146 | 147 | if (DX_FAILED(mCtx->mDevice->CreateTexture2D(&depthStencilDesc, nullptr, &mDefaultDepthStencilTexture2D))) { 148 | return false; 149 | } 150 | 151 | if (DX_FAILED(mCtx->mDevice->CreateDepthStencilView(mDefaultDepthStencilTexture2D, nullptr, &mDefaultDepthStencilView))) { 152 | return false; 153 | } 154 | 155 | // bind the views to the output merger stage 156 | mCtx->mDeviceContext->OMSetRenderTargets(1, &mDefaultRenderTargetView, mDefaultDepthStencilView); 157 | 158 | D3D11_VIEWPORT vp; 159 | vp.TopLeftX = 0.0f; 160 | vp.TopLeftY = 0.0f; 161 | vp.Width = (float)view_width; 162 | vp.Height = (float)view_height; 163 | vp.MinDepth = 0.0f; 164 | vp.MaxDepth = 1.0f; 165 | 166 | mCtx->mDeviceContext->RSSetViewports(1, &vp); 167 | 168 | return true; 169 | } 170 | 171 | void Renderer::UpdateRenderTerrain(const mesh_s &mesh) { 172 | mTerrain.Update(mCtx->mDeviceContext, mesh); 173 | } 174 | 175 | void Renderer::Draw(float delta_seconds, unsigned draw_flags, const camera_s & cam, const demo_info_s &info) { 176 | SetupConstantBuffers(delta_seconds, cam); 177 | 178 | float color[] = { 0.75f, 0.75f, 0.75f, 1.0f }; 179 | mCtx->mDeviceContext->ClearRenderTargetView(mDefaultRenderTargetView, color); 180 | mCtx->mDeviceContext->ClearDepthStencilView(mDefaultDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); 181 | 182 | // draw sky dome 183 | if (draw_flags & DRAW_SKYDOME) { 184 | mCtx->mDeviceContext->RSSetState(mStates.mSolidRS); 185 | mCtx->mDeviceContext->OMSetDepthStencilState(mStates.mDisableDepthDSS, 1); 186 | mCtx->mDeviceContext->OMSetBlendState(mStates.mDisableBlendBS, BLEND_FACTORS, 0xffffffff); 187 | 188 | mShaders.SetSkydomeShaders(mCtx->mDeviceContext, true); { 189 | mCtx->mDeviceContext->VSSetConstantBuffers(0, 1, &mCBuffers.mSkyMVPBuffer); 190 | 191 | mSkydome.Draw(mCtx->mDeviceContext); 192 | } 193 | mShaders.SetSkydomeShaders(mCtx->mDeviceContext, false); 194 | } 195 | 196 | // draw cloud 197 | if (draw_flags & DRAW_CLOUD) { 198 | mCtx->mDeviceContext->RSSetState(mStates.mSolidRS); 199 | mCtx->mDeviceContext->OMSetDepthStencilState(mStates.mDisableDepthDSS, 1); 200 | mCtx->mDeviceContext->OMSetBlendState(mStates.mEnableBlendBS, BLEND_FACTORS, 0xffffffff); 201 | 202 | mShaders.SetCloudShaders(mCtx->mDeviceContext, true); { 203 | mCtx->mDeviceContext->VSSetConstantBuffers(0, 1, &mCBuffers.mSkyMVPBuffer); 204 | mCtx->mDeviceContext->PSSetConstantBuffers(0, 1, &mCBuffers.mCloudMoveBuffer); 205 | 206 | mCloud.Draw(mCtx->mDeviceContext); 207 | } 208 | mShaders.SetCloudShaders(mCtx->mDeviceContext, false); 209 | } 210 | 211 | // draw terrain 212 | if (draw_flags & DRAW_TERRAIN_SOLID) { 213 | mCtx->mDeviceContext->RSSetState(mStates.mSolidRS); 214 | mCtx->mDeviceContext->OMSetDepthStencilState(mStates.mEnableDepthDSS, 1); 215 | mCtx->mDeviceContext->OMSetBlendState(mStates.mDisableBlendBS, BLEND_FACTORS, 0xffffffff); 216 | 217 | mShaders.SetSolidShaders(mCtx->mDeviceContext, true); { 218 | mCtx->mDeviceContext->VSSetConstantBuffers(0, 1, &mCBuffers.mSceneMVBuffer); 219 | mCtx->mDeviceContext->VSSetConstantBuffers(1, 1, &mCBuffers.mSceneMVPBuffer); 220 | mCtx->mDeviceContext->VSSetConstantBuffers(2, 1, &mCBuffers.mTexSizeBuffer); 221 | mCtx->mDeviceContext->PSSetConstantBuffers(0, 1, &mCBuffers.mFogBuffer); 222 | 223 | mTerrain.Draw(mCtx->mDeviceContext, true); 224 | } 225 | mShaders.SetSolidShaders(mCtx->mDeviceContext, false); 226 | } 227 | 228 | if (draw_flags & DRAW_TERRAIN_WIREFRAME) { 229 | mCtx->mDeviceContext->RSSetState(mStates.mWireframeRS); 230 | mCtx->mDeviceContext->OMSetDepthStencilState(mStates.mEnableDepthDSS, 1); 231 | mCtx->mDeviceContext->OMSetBlendState(mStates.mDisableBlendBS, BLEND_FACTORS, 0xffffffff); 232 | 233 | mShaders.SetWireframeShaders(mCtx->mDeviceContext, true); { 234 | mCtx->mDeviceContext->VSSetConstantBuffers(0, 1, &mCBuffers.mSceneMVPBuffer); 235 | 236 | mTerrain.Draw(mCtx->mDeviceContext, false); 237 | } 238 | mShaders.SetWireframeShaders(mCtx->mDeviceContext, false); 239 | } 240 | 241 | // draw text 242 | char text[1024]; 243 | int ms = (int)(info.mUpdateTimeElapsed * 1000.0); 244 | sprintf_s(text, "pos: %.1f, %.1f, %.1f, update: %d ms, triangles: %d, pixel error: %d", 245 | cam.mPos[0], cam.mPos[1], cam.mPos[2], ms, 246 | mTerrain.GetTriangleCount(), 247 | (int)info.mMaxPixelError); 248 | mText.Print(mCtx->mDeviceContext, text); 249 | 250 | mCtx->mDeviceContext->RSSetState(mStates.mSolidRS); 251 | mCtx->mDeviceContext->OMSetDepthStencilState(mStates.mDisableDepthDSS, 1); 252 | mCtx->mDeviceContext->OMSetBlendState(mStates.mEnableBlendBS, BLEND_FACTORS, 0xffffffff); 253 | 254 | mShaders.SetTextShaders(mCtx->mDeviceContext, true); { 255 | mCtx->mDeviceContext->VSSetConstantBuffers(0, 1, &mCBuffers.mTextMVPBuffer); 256 | 257 | mText.Draw(mCtx->mDeviceContext); 258 | } 259 | mShaders.SetTextShaders(mCtx->mDeviceContext, false); 260 | 261 | 262 | mDXGISwapChain->Present(0, 0); 263 | } 264 | 265 | void Renderer::SetupConstantBuffers(float delta_seconds, const camera_s & cam) { 266 | static const vec4_t FOG_COLOR = HORIZONTAL_COLOR; 267 | 268 | // using right-hand coordinate 269 | 270 | float aspect = (float)mViewCX / mViewCY; 271 | 272 | vec3_t skydome_view_to_target; 273 | Vec3Sub(cam.mTarget, cam.mPos, skydome_view_to_target); 274 | 275 | // setup matrices 276 | XMMATRIX persp_matrix = XMMatrixPerspectiveFovRH(Deg2Rad(cam.mFovy), aspect, cam.mZNear, cam.mZFar); 277 | XMMATRIX ortho_matrix = XMMatrixOrthographicRH((float)mViewCX, (float)mViewCY, -1.0f, 1.0f); 278 | XMMATRIX text_trans = XMMatrixTranslation((float)mViewCX * -0.5f + 8.0f, (float)mViewCY * 0.5f - 24.0f, 0.0f); 279 | XMMATRIX skydome_view_matrix = XMMatrixLookAtRH(XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f), Vec3ToXMVECTOR(skydome_view_to_target, 1.0f), XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f)); 280 | XMMATRIX skydome_mvp_matrix = XMMatrixMultiply(skydome_view_matrix, persp_matrix); 281 | XMMATRIX scene_view_matrix = XMMatrixLookAtRH(Vec3ToXMVECTOR(cam.mPos, 1.0f), Vec3ToXMVECTOR(cam.mTarget, 1.0f), Vec3ToXMVECTOR(cam.mUp, 0.0f)); 282 | XMMATRIX scene_mvp_matrix = XMMatrixMultiply(scene_view_matrix, persp_matrix); 283 | XMMATRIX text_mvp_matrix = XMMatrixMultiply(text_trans, ortho_matrix); 284 | 285 | SetConstantBuffer(mCtx, mCBuffers.mTextMVPBuffer, &text_mvp_matrix, sizeof(text_mvp_matrix)); 286 | SetConstantBuffer(mCtx, mCBuffers.mSkyMVPBuffer, &skydome_mvp_matrix, sizeof(skydome_mvp_matrix)); 287 | SetConstantBuffer(mCtx, mCBuffers.mSceneMVPBuffer, &scene_mvp_matrix, sizeof(scene_mvp_matrix)); 288 | SetConstantBuffer(mCtx, mCBuffers.mSceneMVBuffer, &scene_view_matrix, sizeof(scene_view_matrix)); 289 | 290 | XMVECTOR tex_size = XMVectorSet((float)mTerrain.GetTexWidth(), (float)mTerrain.GetTexHeight(), 0.0f, 0.0f); 291 | SetConstantBuffer(mCtx, mCBuffers.mTexSizeBuffer, &tex_size, sizeof(tex_size)); 292 | 293 | XMVECTOR fog = XMVectorSet(FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2], FOG_DENSITY); 294 | SetConstantBuffer(mCtx, mCBuffers.mFogBuffer, &fog, sizeof(fog)); 295 | 296 | mCloudMove[0] += 0.01f * delta_seconds; 297 | mCloudMove[1] += 0.01f * delta_seconds; 298 | 299 | XMVECTOR cloud_move = XMVectorSet(mCloudMove[0], mCloudMove[1], 0.0f, 0.0f); 300 | SetConstantBuffer(mCtx, mCBuffers.mCloudMoveBuffer, &cloud_move, sizeof(cloud_move)); 301 | } 302 | -------------------------------------------------------------------------------- /source/Renderer/Renderer.h: -------------------------------------------------------------------------------- 1 | // Renderer.h 2 | 3 | #pragma once 4 | 5 | #define DRAW_TERRAIN_SOLID 1 6 | #define DRAW_TERRAIN_WIREFRAME 2 7 | #define DRAW_SKYDOME 4 8 | #define DRAW_CLOUD 8 9 | 10 | /* 11 | ================================================================================ 12 | Renderer 13 | ================================================================================ 14 | */ 15 | class Renderer { 16 | public: 17 | Renderer(); 18 | ~Renderer(); 19 | 20 | bool Init(d3d11_ctx_s *ctx, const char_t *res_dir, int test_case); 21 | void Shutdown(); 22 | 23 | bool Reshape(int view_width, int view_height); 24 | 25 | void UpdateRenderTerrain(const mesh_s &mesh); 26 | void Draw(float delta_seconds, unsigned draw_flags, const camera_s & cam, const demo_info_s &info); 27 | 28 | private: 29 | 30 | d3d11_ctx_s * mCtx; 31 | IDXGISwapChain * mDXGISwapChain; 32 | ID3D11RenderTargetView * mDefaultRenderTargetView; 33 | ID3D11Texture2D * mDefaultDepthStencilTexture2D; 34 | ID3D11DepthStencilView * mDefaultDepthStencilView; 35 | 36 | int mViewCX; 37 | int mViewCY; 38 | 39 | ConstantBuffers mCBuffers; 40 | Shaders mShaders; 41 | States mStates; 42 | 43 | 44 | RenderText mText; 45 | RenderSkydome mSkydome; 46 | RenderCloud mCloud; 47 | RenderTerrain mTerrain; 48 | 49 | vec2_t mCloudMove; 50 | 51 | void SetupConstantBuffers(float delta_seconds, const camera_s & cam); 52 | }; 53 | -------------------------------------------------------------------------------- /source/Renderer/Shaders.cpp: -------------------------------------------------------------------------------- 1 | // Shaders.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | Shaders 8 | ================================================================================ 9 | */ 10 | Shaders::Shaders(): 11 | mTextVertexShader(nullptr), 12 | mTextPixelShader(nullptr), 13 | mTextInputLayout(nullptr), 14 | mSkydomeVertexShader(nullptr), 15 | mSkydomePixelShader(nullptr), 16 | mSkydomeInputLayout(nullptr), 17 | mCloudVertexShader(nullptr), 18 | mCloudPixelShader(nullptr), 19 | mCloudInputLayout(nullptr), 20 | mWireframeVertexShader(nullptr), 21 | mWireframePixelShader(nullptr), 22 | mWireframeInputLayout(nullptr), 23 | mSolidVertexShader(nullptr), 24 | mSolidPixelShader(nullptr), 25 | mSolidInputLayout(nullptr) 26 | { 27 | } 28 | 29 | Shaders::~Shaders() { 30 | } 31 | 32 | bool Shaders::Init(d3d11_ctx_s *ctx, const char_t *shader_dir) { 33 | char_t full_filename[MAX_PATH_]; 34 | D3D11_INPUT_ELEMENT_DESC desc[16]; 35 | 36 | // text 37 | sprintf_s_(full_filename, TXT_("%s\\binary\\text.vert.bin"), shader_dir); 38 | 39 | desc[0].SemanticName = "POSITION"; 40 | desc[0].SemanticIndex = 0; 41 | desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; 42 | desc[0].InputSlot = 0; 43 | desc[0].AlignedByteOffset = 0; 44 | desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 45 | desc[0].InstanceDataStepRate = 0; 46 | 47 | desc[1].SemanticName = "TEXCOORD"; 48 | desc[1].SemanticIndex = 0; 49 | desc[1].Format = DXGI_FORMAT_R32G32_FLOAT; 50 | desc[1].InputSlot = 0; 51 | desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; 52 | desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 53 | desc[1].InstanceDataStepRate = 0; 54 | 55 | if (!CreateVertexShaderAndInputLayout(ctx->mDevice, full_filename, desc, 2, mTextVertexShader, mTextInputLayout)) { 56 | return false; 57 | } 58 | 59 | sprintf_s_(full_filename, TXT_("%s\\binary\\text.frag.bin"), shader_dir); 60 | if (!CreatePixelShader(ctx->mDevice, full_filename, mTextPixelShader)) { 61 | return false; 62 | } 63 | 64 | // skydome 65 | sprintf_s_(full_filename, TXT_("%s\\binary\\skydome.vert.bin"), shader_dir); 66 | 67 | desc[0].SemanticName = "POSITION"; 68 | desc[0].SemanticIndex = 0; 69 | desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; 70 | desc[0].InputSlot = 0; 71 | desc[0].AlignedByteOffset = 0; 72 | desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 73 | desc[0].InstanceDataStepRate = 0; 74 | 75 | desc[1].SemanticName = "COLOR"; 76 | desc[1].SemanticIndex = 0; 77 | desc[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; 78 | desc[1].InputSlot = 0; 79 | desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; 80 | desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 81 | desc[1].InstanceDataStepRate = 0; 82 | 83 | if (!CreateVertexShaderAndInputLayout(ctx->mDevice, full_filename, desc, 2, mSkydomeVertexShader, mSkydomeInputLayout)) { 84 | return false; 85 | } 86 | 87 | sprintf_s_(full_filename, TXT_("%s\\binary\\skydome.frag.bin"), shader_dir); 88 | if (!CreatePixelShader(ctx->mDevice, full_filename, mSkydomePixelShader)) { 89 | return false; 90 | } 91 | 92 | // cloud 93 | sprintf_s_(full_filename, TXT_("%s\\binary\\cloud.vert.bin"), shader_dir); 94 | 95 | desc[0].SemanticName = "POSITION"; 96 | desc[0].SemanticIndex = 0; 97 | desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; 98 | desc[0].InputSlot = 0; 99 | desc[0].AlignedByteOffset = 0; 100 | desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 101 | desc[0].InstanceDataStepRate = 0; 102 | 103 | desc[1].SemanticName = "COLOR"; 104 | desc[1].SemanticIndex = 0; 105 | desc[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT; 106 | desc[1].InputSlot = 0; 107 | desc[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; 108 | desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 109 | desc[1].InstanceDataStepRate = 0; 110 | 111 | if (!CreateVertexShaderAndInputLayout(ctx->mDevice, full_filename, desc, 2, mCloudVertexShader, mCloudInputLayout)) { 112 | return false; 113 | } 114 | 115 | sprintf_s_(full_filename, TXT_("%s\\binary\\cloud.frag.bin"), shader_dir); 116 | if (!CreatePixelShader(ctx->mDevice, full_filename, mCloudPixelShader)) { 117 | return false; 118 | } 119 | 120 | // wireframe mode 121 | sprintf_s_(full_filename, TXT_("%s\\binary\\wireframe.vert.bin"), shader_dir); 122 | 123 | desc[0].SemanticName = "POSITION"; 124 | desc[0].SemanticIndex = 0; 125 | desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; 126 | desc[0].InputSlot = 0; 127 | desc[0].AlignedByteOffset = 0; 128 | desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 129 | desc[0].InstanceDataStepRate = 0; 130 | 131 | if (!CreateVertexShaderAndInputLayout(ctx->mDevice, full_filename, desc, 1, mWireframeVertexShader, mWireframeInputLayout)) { 132 | return false; 133 | } 134 | 135 | sprintf_s_(full_filename, TXT_("%s\\binary\\wireframe.frag.bin"), shader_dir); 136 | if (!CreatePixelShader(ctx->mDevice, full_filename, mWireframePixelShader)) { 137 | return false; 138 | } 139 | 140 | // solid mode 141 | sprintf_s_(full_filename, TXT_("%s\\binary\\solid.vert.bin"), shader_dir); 142 | 143 | desc[0].SemanticName = "POSITION"; 144 | desc[0].SemanticIndex = 0; 145 | desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; 146 | desc[0].InputSlot = 0; 147 | desc[0].AlignedByteOffset = 0; 148 | desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 149 | desc[0].InstanceDataStepRate = 0; 150 | 151 | if (!CreateVertexShaderAndInputLayout(ctx->mDevice, full_filename, desc, 1, mSolidVertexShader, mSolidInputLayout)) { 152 | return false; 153 | } 154 | 155 | sprintf_s_(full_filename, TXT_("%s\\binary\\solid.frag.bin"), shader_dir); 156 | if (!CreatePixelShader(ctx->mDevice, full_filename, mSolidPixelShader)) { 157 | return false; 158 | } 159 | 160 | return true; 161 | } 162 | 163 | void Shaders::Shutdown() { 164 | DX_SAFE_RELEASE(mSolidInputLayout); 165 | DX_SAFE_RELEASE(mSolidPixelShader); 166 | DX_SAFE_RELEASE(mSolidVertexShader); 167 | 168 | DX_SAFE_RELEASE(mWireframeInputLayout); 169 | DX_SAFE_RELEASE(mWireframePixelShader); 170 | DX_SAFE_RELEASE(mWireframeVertexShader); 171 | 172 | DX_SAFE_RELEASE(mCloudInputLayout); 173 | DX_SAFE_RELEASE(mCloudVertexShader); 174 | DX_SAFE_RELEASE(mCloudPixelShader); 175 | 176 | DX_SAFE_RELEASE(mSkydomeInputLayout); 177 | DX_SAFE_RELEASE(mSkydomeVertexShader); 178 | DX_SAFE_RELEASE(mSkydomePixelShader); 179 | 180 | DX_SAFE_RELEASE(mTextInputLayout); 181 | DX_SAFE_RELEASE(mTextVertexShader); 182 | DX_SAFE_RELEASE(mTextPixelShader); 183 | } 184 | 185 | void Shaders::SetTextShaders(ID3D11DeviceContext * device_context, bool set) { 186 | device_context->IASetInputLayout(set ? mTextInputLayout : nullptr); 187 | device_context->VSSetShader(set ? mTextVertexShader : nullptr, nullptr, 0); 188 | device_context->PSSetShader(set ? mTextPixelShader : nullptr, nullptr, 0); 189 | } 190 | 191 | void Shaders::SetSkydomeShaders(ID3D11DeviceContext * device_context, bool set) { 192 | device_context->IASetInputLayout(set ? mSkydomeInputLayout : nullptr); 193 | device_context->VSSetShader(set ? mSkydomeVertexShader : nullptr, nullptr, 0); 194 | device_context->PSSetShader(set ? mSkydomePixelShader : nullptr, nullptr, 0); 195 | } 196 | 197 | void Shaders::SetCloudShaders(ID3D11DeviceContext * device_context, bool set) { 198 | device_context->IASetInputLayout(set ? mCloudInputLayout : nullptr); 199 | device_context->VSSetShader(set ? mCloudVertexShader : nullptr, nullptr, 0); 200 | device_context->PSSetShader(set ? mCloudPixelShader : nullptr, nullptr, 0); 201 | } 202 | 203 | void Shaders::SetWireframeShaders(ID3D11DeviceContext * device_context, bool set) { 204 | device_context->IASetInputLayout(set ? mWireframeInputLayout : nullptr); 205 | device_context->VSSetShader(set ? mWireframeVertexShader : nullptr, nullptr, 0); 206 | device_context->PSSetShader(set ? mWireframePixelShader : nullptr, nullptr, 0); 207 | } 208 | 209 | void Shaders::SetSolidShaders(ID3D11DeviceContext * device_context, bool set) { 210 | device_context->IASetInputLayout(set ? mSolidInputLayout : nullptr); 211 | device_context->VSSetShader(set ? mSolidVertexShader : nullptr, nullptr, 0); 212 | device_context->PSSetShader(set ? mSolidPixelShader : nullptr, nullptr, 0); 213 | } 214 | -------------------------------------------------------------------------------- /source/Renderer/Shaders.h: -------------------------------------------------------------------------------- 1 | // Shaders.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | Shaders 8 | ================================================================================ 9 | */ 10 | class Shaders { 11 | public: 12 | 13 | Shaders(); 14 | ~Shaders(); 15 | 16 | bool Init(d3d11_ctx_s *ctx, const char_t *shader_dir); 17 | void Shutdown(); 18 | 19 | void SetTextShaders(ID3D11DeviceContext * device_context, bool set); 20 | void SetSkydomeShaders(ID3D11DeviceContext * device_context, bool set); 21 | void SetCloudShaders(ID3D11DeviceContext * device_context, bool set); 22 | void SetWireframeShaders(ID3D11DeviceContext * device_context, bool set); 23 | void SetSolidShaders(ID3D11DeviceContext * device_context, bool set); 24 | 25 | public: 26 | 27 | // shaders 28 | ID3D11VertexShader * mTextVertexShader; 29 | ID3D11PixelShader * mTextPixelShader; 30 | ID3D11InputLayout * mTextInputLayout; 31 | 32 | ID3D11VertexShader * mSkydomeVertexShader; 33 | ID3D11PixelShader * mSkydomePixelShader; 34 | ID3D11InputLayout * mSkydomeInputLayout; 35 | 36 | ID3D11VertexShader * mCloudVertexShader; 37 | ID3D11PixelShader * mCloudPixelShader; 38 | ID3D11InputLayout * mCloudInputLayout; 39 | 40 | ID3D11VertexShader * mWireframeVertexShader; 41 | ID3D11PixelShader * mWireframePixelShader; 42 | ID3D11InputLayout * mWireframeInputLayout; 43 | 44 | ID3D11VertexShader * mSolidVertexShader; 45 | ID3D11PixelShader * mSolidPixelShader; 46 | ID3D11InputLayout * mSolidInputLayout; 47 | }; 48 | 49 | -------------------------------------------------------------------------------- /source/Renderer/States.cpp: -------------------------------------------------------------------------------- 1 | // States.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | States 8 | ================================================================================ 9 | */ 10 | States::States() : 11 | mSolidRS(nullptr), 12 | mWireframeRS(nullptr), 13 | mDisableDepthDSS(nullptr), 14 | mEnableDepthDSS(nullptr), 15 | mDisableBlendBS(nullptr), 16 | mEnableBlendBS(nullptr) 17 | { 18 | } 19 | 20 | States::~States() { 21 | // do nothing 22 | } 23 | 24 | bool States::Init(d3d11_ctx_s *ctx) { 25 | D3D11_RASTERIZER_DESC ras_desc; 26 | 27 | ras_desc.FillMode = D3D11_FILL_SOLID; 28 | ras_desc.CullMode = D3D11_CULL_BACK; 29 | ras_desc.FrontCounterClockwise = TRUE; 30 | ras_desc.DepthBias = 0; 31 | ras_desc.DepthBiasClamp = 0.0f; 32 | ras_desc.SlopeScaledDepthBias = 0.0f; 33 | ras_desc.DepthClipEnable = TRUE; 34 | ras_desc.ScissorEnable = FALSE; 35 | ras_desc.MultisampleEnable = FALSE; 36 | ras_desc.AntialiasedLineEnable = FALSE; 37 | 38 | if (DX_FAILED(ctx->mDevice->CreateRasterizerState(&ras_desc, &mSolidRS))) { 39 | return false; 40 | } 41 | 42 | ras_desc.FillMode = D3D11_FILL_WIREFRAME; 43 | ras_desc.CullMode = D3D11_CULL_BACK; 44 | ras_desc.FrontCounterClockwise = TRUE; 45 | ras_desc.DepthBias = 0; 46 | ras_desc.DepthBiasClamp = 0.0f; 47 | ras_desc.SlopeScaledDepthBias = -1.0f; 48 | ras_desc.DepthClipEnable = TRUE; 49 | ras_desc.ScissorEnable = FALSE; 50 | ras_desc.MultisampleEnable = FALSE; 51 | ras_desc.AntialiasedLineEnable = FALSE; 52 | 53 | if (DX_FAILED(ctx->mDevice->CreateRasterizerState(&ras_desc, &mWireframeRS))) { 54 | return false; 55 | } 56 | 57 | 58 | D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; 59 | memset(&depth_stencil_desc, 0, sizeof(depth_stencil_desc)); 60 | 61 | depth_stencil_desc.DepthEnable = FALSE; 62 | depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; 63 | depth_stencil_desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 64 | depth_stencil_desc.StencilEnable = FALSE; 65 | 66 | if (DX_FAILED(ctx->mDevice->CreateDepthStencilState(&depth_stencil_desc, &mDisableDepthDSS))) { 67 | return false; 68 | } 69 | 70 | depth_stencil_desc.DepthEnable = TRUE; 71 | depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 72 | depth_stencil_desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; 73 | depth_stencil_desc.StencilEnable = FALSE; 74 | 75 | if (DX_FAILED(ctx->mDevice->CreateDepthStencilState(&depth_stencil_desc, &mEnableDepthDSS))) { 76 | return false; 77 | } 78 | 79 | 80 | D3D11_BLEND_DESC blend_desc = { 0 }; 81 | 82 | blend_desc.AlphaToCoverageEnable = FALSE; 83 | blend_desc.IndependentBlendEnable = FALSE; 84 | blend_desc.RenderTarget[0].BlendEnable = FALSE; 85 | blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 86 | 87 | if (DX_FAILED(ctx->mDevice->CreateBlendState(&blend_desc, &mDisableBlendBS))) { 88 | return false; 89 | } 90 | 91 | blend_desc.AlphaToCoverageEnable = FALSE; 92 | blend_desc.IndependentBlendEnable = FALSE; 93 | blend_desc.RenderTarget[0].BlendEnable = TRUE; 94 | blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 95 | blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 96 | blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 97 | blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 98 | blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; 99 | blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 100 | blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 101 | 102 | if (DX_FAILED(ctx->mDevice->CreateBlendState(&blend_desc, &mEnableBlendBS))) { 103 | return false; 104 | } 105 | 106 | return true; 107 | } 108 | 109 | void States::Shutdown() { 110 | DX_SAFE_RELEASE(mEnableBlendBS); 111 | DX_SAFE_RELEASE(mDisableBlendBS); 112 | DX_SAFE_RELEASE(mEnableDepthDSS); 113 | DX_SAFE_RELEASE(mDisableDepthDSS); 114 | DX_SAFE_RELEASE(mWireframeRS); 115 | DX_SAFE_RELEASE(mSolidRS); 116 | } 117 | -------------------------------------------------------------------------------- /source/Renderer/States.h: -------------------------------------------------------------------------------- 1 | // States.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | States 8 | ================================================================================ 9 | */ 10 | class States { 11 | public: 12 | 13 | States(); 14 | ~States(); 15 | 16 | bool Init(d3d11_ctx_s *ctx); 17 | void Shutdown(); 18 | 19 | public: 20 | 21 | ID3D11RasterizerState * mSolidRS; 22 | ID3D11RasterizerState * mWireframeRS; 23 | 24 | ID3D11DepthStencilState * mDisableDepthDSS; 25 | ID3D11DepthStencilState * mEnableDepthDSS; 26 | 27 | ID3D11BlendState * mDisableBlendBS; 28 | ID3D11BlendState * mEnableBlendBS; 29 | }; 30 | -------------------------------------------------------------------------------- /source/Shared.cpp: -------------------------------------------------------------------------------- 1 | // Shared.cpp 2 | 3 | #include "Precompiled.h" 4 | #include "png.h" 5 | 6 | /* 7 | ================================================================================ 8 | Math 9 | ================================================================================ 10 | */ 11 | 12 | void Vec3Copy(const vec3_t in, vec3_t out) { 13 | memcpy(out, in, sizeof(vec3_t)); 14 | } 15 | 16 | void Vec3Set(vec3_t v, float x, float y, float z) { 17 | v[0] = x; 18 | v[1] = y; 19 | v[2] = z; 20 | } 21 | 22 | void Vec3Add(const vec3_t a, const vec3_t b, vec3_t out) { 23 | out[0] = a[0] + b[0]; 24 | out[1] = a[1] + b[1]; 25 | out[2] = a[2] + b[2]; 26 | } 27 | 28 | void Vec3Sub(const vec3_t a, const vec3_t b, vec3_t out) { 29 | out[0] = a[0] - b[0]; 30 | out[1] = a[1] - b[1]; 31 | out[2] = a[2] - b[2]; 32 | } 33 | 34 | float Vec3Dot(const vec3_t a, const vec3_t b) { 35 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 36 | } 37 | 38 | float Vec3Normalize(vec3_t v) { 39 | float len = Vec3Length(v); 40 | if (len > 0.0f) { 41 | float i = 1.0f / len; 42 | v[0] *= i; 43 | v[1] *= i; 44 | v[2] *= i; 45 | } 46 | 47 | return len; 48 | } 49 | 50 | float Vec3Length(const vec3_t v) { 51 | return sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 52 | } 53 | 54 | float Vec3SquareLength(const vec3_t v) { 55 | return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; 56 | } 57 | 58 | void Vec3Mul(const vec3_t a, float f, vec3_t out) { 59 | out[0] = a[0] * f; 60 | out[1] = a[1] * f; 61 | out[2] = a[2] * f; 62 | } 63 | 64 | float Deg2Rad(float deg) { 65 | return deg * PI / 180.0f; 66 | } 67 | 68 | float Rad2Deg(float rad) { 69 | return rad * 180.0f / PI; 70 | } 71 | 72 | XMVECTOR Vec3ToXMVECTOR(const vec3_t v, float w) { 73 | return XMVectorSet(v[0], v[1], v[2], w); 74 | } 75 | 76 | void XMVECTORToVec3(const XMVECTOR &in, vec3_t out) { 77 | out[0] = in.m128_f32[0]; 78 | out[1] = in.m128_f32[1]; 79 | out[2] = in.m128_f32[2]; 80 | } 81 | 82 | float ClampYaw(float yaw) { 83 | while (yaw < 0.0f) { 84 | yaw += 360.0f; 85 | } 86 | 87 | while (yaw > 360.0f) { 88 | yaw -= 360.0f; 89 | } 90 | 91 | return yaw; 92 | } 93 | 94 | float ClampPitch(float pitch) { 95 | if (pitch < -89.0f) { 96 | pitch = -89.0f; 97 | } 98 | 99 | if (pitch > 89.0f) { 100 | pitch = 89.0f; 101 | } 102 | 103 | return pitch; 104 | } 105 | 106 | void Vec4Copy(const vec4_t in, vec4_t out) { 107 | memcpy(out, in, sizeof(vec4_t)); 108 | } 109 | 110 | void Vec4Set(vec4_t v, float x, float y, float z, float w) { 111 | v[0] = x; 112 | v[1] = y; 113 | v[2] = z; 114 | v[3] = w; 115 | } 116 | 117 | void Vec4Sub(const vec4_t a, const vec4_t b, vec4_t out) { 118 | out[0] = a[0] - b[0]; 119 | out[1] = a[1] - b[1]; 120 | out[2] = a[2] - b[2]; 121 | out[3] = a[3] - b[3]; 122 | } 123 | 124 | void Vec4MulAdd(const vec4_t a, float f, const vec4_t b, vec4_t out) { 125 | out[0] = a[0] * f + b[0]; 126 | out[1] = a[1] * f + b[1]; 127 | out[2] = a[2] * f + b[2]; 128 | out[3] = a[3] * f + b[3]; 129 | } 130 | 131 | void frustum_plane_s::Setup(int viewport_width, int viewport_height, const camera_s &cam) { 132 | float tan1 = tanf(Deg2Rad(cam.mFovy * 0.5f)); 133 | float d = (float)viewport_height * 0.5f / tan1; 134 | float tan2 = (float)viewport_width * 0.5f / d; 135 | float fovx = Rad2Deg(atanf(tan2)) * 2.0f; 136 | 137 | vec3_t forward; 138 | Vec3Sub(cam.mTarget, cam.mPos, forward); 139 | Vec3Normalize(forward); 140 | 141 | XMVECTOR up = Vec3ToXMVECTOR(cam.mUp, 0.0f); 142 | XMVECTOR f = Vec3ToXMVECTOR(forward, 0.0f); 143 | XMMATRIX m; 144 | 145 | float deg = -(90.0f - fovx * 0.5f); 146 | m = DirectX::XMMatrixRotationAxis(up, Deg2Rad(deg)); 147 | XMVECTOR n = DirectX::XMVector4Transform(f, m); 148 | mLeftPlane[0] = n.m128_f32[0]; 149 | mLeftPlane[1] = n.m128_f32[1]; 150 | mLeftPlane[2] = n.m128_f32[2]; 151 | mLeftPlane[3] = -Vec3Dot(cam.mPos, mLeftPlane); 152 | 153 | deg = (90.0f - fovx * 0.5f); 154 | m = DirectX::XMMatrixRotationAxis(up, Deg2Rad(deg)); 155 | n = DirectX::XMVector4Transform(f, m); 156 | mRightPlane[0] = n.m128_f32[0]; 157 | mRightPlane[1] = n.m128_f32[1]; 158 | mRightPlane[2] = n.m128_f32[2]; 159 | mRightPlane[3] = -Vec3Dot(cam.mPos, mRightPlane); 160 | } 161 | 162 | bool frustum_plane_s::CullHorizontalCircle(const vec3_t ¢er, float radius) const { 163 | vec3_t temp; 164 | 165 | memcpy(temp, mLeftPlane, sizeof(float) * 3); 166 | float dist = Vec3Dot(temp, center) + mLeftPlane[3]; 167 | if (dist < -radius) { 168 | return true; 169 | } 170 | 171 | memcpy(temp, mRightPlane, sizeof(float) * 3); 172 | dist = Vec3Dot(temp, center) + mRightPlane[3]; 173 | if (dist < -radius) { 174 | return true; 175 | } 176 | 177 | return false; 178 | } 179 | 180 | /* 181 | ================================================================================ 182 | Demo 183 | ================================================================================ 184 | */ 185 | const test_data_s TEST_DATA[2] = { 186 | // Grand Canyon 187 | // horizontal: 60 meters / inter-pixel spacing, vertical: 10 meters / pixel unit 188 | { TXT_("gcanyon_height_4k2k.png"), TXT_("gcanyon_color_4k2k.png"), 14.0f / 60.0f }, // exaggerate the elevation by 40% to make the demo more challenging. 189 | 190 | // Puget Sound 191 | // horizontal: 40 meters / inter-pixel spacing, vertical: 0.1 meters / pixel unit 192 | { TXT_("ps_height_4k.png"), TXT_("ps_texture_4k.png"), 0.1f / 40.0f } 193 | }; 194 | 195 | void ToggleFlags(unsigned int &flags, unsigned int f) { 196 | if (flags & f) { 197 | flags &= ~f; 198 | } 199 | else { 200 | flags |= f; 201 | } 202 | } 203 | 204 | /* 205 | ================================================================================ 206 | Log 207 | ================================================================================ 208 | */ 209 | void Sys_Error(const char_t *file, int line, const char_t *fmt, ...) { 210 | char_t buffer[4096]; 211 | 212 | sprintf_s_(buffer, TXT_("file: %s, line: %d, msg: "), file, line); 213 | int len = (int)strlen_(buffer); 214 | 215 | va_list argptr; 216 | va_start(argptr, fmt); 217 | vsprintf_s_(buffer + len, 4096 - len, fmt, argptr); 218 | va_end(argptr); 219 | 220 | fprintf_s_(stderr, TXT_("%s\n"), buffer); 221 | } 222 | 223 | /* 224 | ================================================================================ 225 | File 226 | ================================================================================ 227 | */ 228 | static int FileSize(FILE * f) { 229 | int pos = ftell(f); 230 | fseek(f, 0, SEEK_END); 231 | int size = ftell(f); 232 | fseek(f, pos, SEEK_SET); 233 | 234 | return size; 235 | } 236 | 237 | int File_LoadBinary(const char_t * filename, char *buffer, int buffer_size) { 238 | int read = 0; 239 | 240 | FILE * f = nullptr; 241 | if (fopen_s_(&f, filename, TXT_("rb")) == 0) { 242 | int size = FileSize(f); 243 | if (size <= buffer_size) { 244 | read = (int)fread(buffer, 1, (size_t)size, f); 245 | } 246 | fclose(f); 247 | } 248 | 249 | return read; 250 | } 251 | 252 | /* 253 | ================================================================================ 254 | Timer 255 | ================================================================================ 256 | */ 257 | static double gSecondsPerCycle = 1.0; 258 | static __int64 gBaseCycle = 0; 259 | 260 | void Sys_InitTimer() { 261 | __int64 f; 262 | QueryPerformanceFrequency((LARGE_INTEGER*)&f); //call QueryPerformanceFrequency only once, this value would not change during machine running 263 | gSecondsPerCycle = 1.0 / f; 264 | 265 | QueryPerformanceCounter((LARGE_INTEGER*)&gBaseCycle); 266 | } 267 | 268 | double Sys_GetRelativeTime() { 269 | __int64 c; 270 | QueryPerformanceCounter((LARGE_INTEGER*)&c); 271 | return (c - gBaseCycle) * gSecondsPerCycle; 272 | } 273 | 274 | /* 275 | ================================================================================ 276 | String 277 | ================================================================================ 278 | */ 279 | static char_t * FindDoubleDots(char_t *s) { 280 | char_t * pc = strstr_(s, TXT_("..\\")); 281 | if (!pc) { 282 | pc = strstr_(s, TXT_("../")); 283 | } 284 | return pc; 285 | } 286 | 287 | static char_t * RFindSlash(char_t *s) { 288 | char_t * pc = strrchr_(s, TXT_('\\')); 289 | if (!pc) { 290 | pc = strrchr_(s, TXT_('/')); 291 | } 292 | return pc; 293 | } 294 | 295 | void Str_EraseDoubleDots(char_t *s) { 296 | char_t sl[2][MAX_PATH_]; 297 | 298 | strcpy_s_(sl[0], s); 299 | strcpy_s_(sl[1], s); 300 | 301 | int srcidx = 0; 302 | int dstidx = 1 - srcidx; 303 | 304 | char_t * pc = FindDoubleDots(sl[srcidx]); 305 | while (pc) { 306 | *pc = 0; 307 | 308 | char_t * pc1 = RFindSlash(sl[srcidx]); 309 | if (pc1) { 310 | *pc1 = 0; 311 | 312 | char_t * pc2 = RFindSlash(sl[srcidx]); 313 | if (pc2) { 314 | pc2[1] = 0; 315 | strcpy_s_(sl[dstidx], sl[srcidx]); 316 | strcat_s_(sl[dstidx], pc + 3); 317 | 318 | srcidx = 1 - srcidx; 319 | dstidx = 1 - srcidx; 320 | 321 | pc = FindDoubleDots(sl[srcidx]); 322 | } 323 | else { 324 | break; 325 | } 326 | 327 | } 328 | else { 329 | break; 330 | } 331 | } 332 | 333 | strcpy_s_(s, MAX_PATH_, sl[srcidx]); 334 | } 335 | 336 | void Str_ExtractDirSelf(char_t *s) { 337 | char_t * pc = strrchr_(s, TXT_('\\')); 338 | if (!pc) { 339 | pc = strrchr_(s, '/'); 340 | } 341 | 342 | if (pc) { 343 | *pc = 0; 344 | } 345 | } 346 | 347 | void Str_ExtractExeDir(const char_t *exe, char_t *dir, int dir_size) { 348 | strcpy_s_(dir, dir_size, exe); 349 | Str_EraseDoubleDots(dir); 350 | Str_ExtractDirSelf(dir); 351 | } 352 | 353 | int Str_ToAnsi(const char_t *src, char * dst, int dst_chars) { 354 | #ifdef _UNICODE 355 | 356 | if (!src) { 357 | if (dst && dst_chars > 0) { 358 | dst[0] = 0; 359 | } 360 | return 0; 361 | } 362 | 363 | int wide_chars = (int)strlen_(src); 364 | int need_chars = WideCharToMultiByte(CP_ACP, 0, src, wide_chars, nullptr, 0, nullptr, nullptr); // returns the number of characters 365 | if (!dst) { 366 | return need_chars; 367 | } 368 | 369 | if (dst_chars < need_chars + 1) { 370 | dst[0] = 0; 371 | SYS_ERROR(TXT_("ansi buffer too small\n")); 372 | return 0; 373 | } 374 | 375 | int translen = WideCharToMultiByte(CP_ACP, 0, src, wide_chars, dst, dst_chars, nullptr, nullptr); 376 | dst[translen] = 0; 377 | 378 | return translen; 379 | 380 | #else 381 | 382 | int src_chars = (int)strlen_(src); 383 | if (dst_chars < src_chars + 1) { 384 | dst[0] = 0; 385 | SYS_ERROR(TXT_("ansi buffer too small\n"); 386 | return 0; 387 | } 388 | 389 | strcpy_s_(dst, dst_chars, src); 390 | 391 | return src_chars; 392 | 393 | #endif 394 | } 395 | 396 | int Str_FrAnsi(const char *src, char_t * dst, int dst_chars) { 397 | #ifdef _UNICODE 398 | 399 | if (!src) { 400 | if (dst && dst_chars > 0) { 401 | dst[0] = 0; 402 | } 403 | return 0; 404 | } 405 | 406 | 407 | int ansi_chars = (int)strlen(src); 408 | int need_chars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, ansi_chars, nullptr, 0); // returns the number of characters 409 | if (!dst) { 410 | return need_chars; 411 | } 412 | 413 | if (dst_chars < need_chars + 1) { 414 | dst[0] = 0; 415 | SYS_ERROR(TXT_("wide buffer too small\n")); 416 | return 0; 417 | } 418 | 419 | int translen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, src, ansi_chars, dst, dst_chars); 420 | dst[translen] = 0; 421 | 422 | return translen; 423 | 424 | #else 425 | 426 | int src_chars = (int)wcslen(src); 427 | if (dst_chars < src_chars + 1) { 428 | dst[0] = 0; 429 | SYS_ERROR(TXT_("wide buffer too small\n"); 430 | return 0; 431 | } 432 | 433 | wcscpy_s(dst, dst_chars, src); 434 | 435 | return src_chars; 436 | 437 | #endif 438 | } 439 | 440 | /* 441 | ================================================================================ 442 | Image 443 | ================================================================================ 444 | */ 445 | bool ReadPNG(const char_t *filename, image_s *image) { 446 | char ansi_filename[MAX_PATH_]; 447 | Str_ToAnsi(filename, ansi_filename, MAX_PATH_); 448 | 449 | png_image image_png; 450 | memset(&image_png, 0, sizeof(image_png)); 451 | image_png.version = PNG_IMAGE_VERSION; 452 | 453 | if (png_image_begin_read_from_file(&image_png, ansi_filename)) { 454 | size_t pixel_size = 0; 455 | 456 | // check file format 457 | switch (image_png.format) { 458 | case PNG_FORMAT_GRAY: 459 | image->mFormat = IMG_FORMAT_1BYTE_GRAY; 460 | pixel_size = 1; 461 | break; 462 | case PNG_FORMAT_LINEAR_Y: 463 | image->mFormat = IMG_FORMAT_2BYTE_GRAY; 464 | pixel_size = 2; 465 | break; 466 | case PNG_FORMAT_RGB: 467 | image->mFormat = IMG_FORMAT_1BYTE_RGB; 468 | pixel_size = 3; 469 | break; 470 | case PNG_FORMAT_RGBA: 471 | image->mFormat = IMG_FORMAT_1BYTE_RGBA; 472 | pixel_size = 4; 473 | break; 474 | default: 475 | SYS_ERROR(L"unsupported format\n"); 476 | return false; 477 | } 478 | 479 | size_t size = PNG_IMAGE_SIZE(image_png); // get image size 480 | png_bytep buffer_png = (png_bytep)malloc(size); 481 | 482 | if (png_image_finish_read(&image_png, NULL/*background*/, buffer_png, 0/*row_stride*/, nullptr/*colormap*/)) { 483 | 484 | image->mCX = image_png.width; 485 | image->mCY = image_png.height; 486 | image->mData = malloc(image_png.height * image_png.width * pixel_size); 487 | memcpy(image->mData, buffer_png, image_png.height * image_png.width * pixel_size); 488 | 489 | png_image_free(&image_png); 490 | free(buffer_png); 491 | 492 | return true; 493 | } 494 | else { 495 | png_image_free(&image_png); 496 | free(buffer_png); 497 | 498 | SYS_ERROR(L"png_image_finish_read failed\n"); 499 | return false; 500 | } 501 | } 502 | else { 503 | SYS_ERROR(L"png_image_begin_read_from_file failed\n"); 504 | return false; 505 | } 506 | } 507 | 508 | bool SavePNG(const char_t *filename, const image_s *image) { 509 | if (!image->mData || image->mCX < 1 || image->mCY < 1) { 510 | SYS_ERROR(L"bad data\n"); 511 | return false; 512 | } 513 | 514 | png_uint_32 dst_format = 0; 515 | size_t pixel_size = 0; 516 | 517 | switch (image->mFormat) { 518 | case IMG_FORMAT_1BYTE_GRAY: 519 | dst_format = PNG_FORMAT_GRAY; 520 | pixel_size = 1; 521 | break; 522 | case IMG_FORMAT_2BYTE_GRAY: 523 | dst_format = PNG_FORMAT_LINEAR_Y; 524 | pixel_size = 2; 525 | break; 526 | case IMG_FORMAT_1BYTE_RGB: 527 | dst_format = PNG_FORMAT_RGB; 528 | pixel_size = 3; 529 | break; 530 | case IMG_FORMAT_1BYTE_RGBA: 531 | dst_format = PNG_FORMAT_RGBA; 532 | pixel_size = 4; 533 | break; 534 | default: 535 | SYS_ERROR(L"unsupported format\n"); 536 | return false; 537 | } 538 | 539 | png_image image_png; 540 | memset(&image_png, 0, sizeof(image_png)); 541 | image_png.version = PNG_IMAGE_VERSION; 542 | image_png.width = image->mCX; 543 | image_png.height = image->mCY; 544 | image_png.format = dst_format; 545 | 546 | 547 | size_t size = PNG_IMAGE_SIZE(image_png); // get image size 548 | png_bytep buffer_png = (png_bytep)malloc(size); 549 | 550 | /* 551 | // convert height direction 552 | for (int h = 0; h < image->mCY; ++h) { 553 | const char * src_line = (const char *)image->mData + h * image->mCX * pixel_size; 554 | png_bytep dst_line = buffer_png + (image->mCY - h - 1) * image->mCX * pixel_size; 555 | memcpy(dst_line, src_line, image->mCX * pixel_size); 556 | } 557 | */ 558 | memcpy(buffer_png, image->mData, image->mCY * image->mCX * pixel_size); 559 | 560 | // save to png file 561 | char ansi_filename[MAX_PATH_]; 562 | Str_ToAnsi(filename, ansi_filename, MAX_PATH_); 563 | if (png_image_write_to_file(&image_png, ansi_filename, 0, buffer_png, PNG_IMAGE_ROW_STRIDE(image_png), nullptr/*colormap*/)) { 564 | png_image_free(&image_png); 565 | free(buffer_png); 566 | return true; 567 | } 568 | else { 569 | SYS_ERROR(L"png_image_write_to_file failed\n"); 570 | free(buffer_png); 571 | return false; 572 | } 573 | } 574 | 575 | void FreeImg(image_s *image) { 576 | if (image->mData) { 577 | free(image->mData); 578 | image->mData = nullptr; 579 | image->mCX = image->mCY = 0; 580 | } 581 | } 582 | -------------------------------------------------------------------------------- /source/Shared.h: -------------------------------------------------------------------------------- 1 | // Shared.h 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | using namespace DirectX; 9 | 10 | /* 11 | ================================================================================ 12 | Memory 13 | ================================================================================ 14 | */ 15 | 16 | #ifdef _DEBUG 17 | # include 18 | # define NEW__ new (_NORMAL_BLOCK, __FILE__, __LINE__) 19 | #else 20 | # define NEW__ new 21 | #endif 22 | 23 | #define MAX_PATH_ 260 24 | 25 | #ifdef _UNICODE 26 | 27 | typedef wchar_t char_t; 28 | 29 | # define _L(x) __L(x) 30 | # define __L(x) L ## x 31 | # define __SRC_FILE__ _L(__FILE__) 32 | 33 | # define TXT_(x) L ## x 34 | 35 | # define strlen_ wcslen 36 | # define strstr_ wcsstr 37 | # define strrchr_ wcsrchr 38 | # define strcpy_s_ wcscpy_s 39 | # define strcat_s_ wcscat_s 40 | # define fopen_s_ _wfopen_s 41 | # define sprintf_s_ swprintf_s 42 | # define vsprintf_s_ vswprintf_s 43 | # define fprintf_s_ fwprintf_s 44 | 45 | #else 46 | 47 | typedef char char_t; 48 | 49 | # define __SRC_FILE__ __FILE__ 50 | 51 | # define TXT_(x) x 52 | 53 | # define strlen_ strlen 54 | # define strstr_ strstr 55 | # define strrchr_ strrchr 56 | # define strcpy_s_ strcpy_s 57 | # define strcat_s_ strcat_s 58 | # define fopen_s_ fopen_s 59 | # define sprintf_s_ sprintf_s 60 | # define vsprintf_s_ vsprintf_s 61 | # define fprintf_s_ fprintf_s 62 | 63 | #endif 64 | 65 | #define SAFE_FREE(p) do { if (p) { free(p); p = nullptr; } } while (0) 66 | 67 | /* 68 | ================================================================================ 69 | Math 70 | ================================================================================ 71 | */ 72 | 73 | typedef float vec2_t[2]; 74 | typedef float vec3_t[3]; 75 | typedef float vec4_t[4]; 76 | 77 | #define PI 3.14159265358979323846f 78 | 79 | template 80 | T Square(T v) { return v * v; } 81 | void Vec3Copy(const vec3_t in, vec3_t out); 82 | void Vec3Set(vec3_t v, float x, float y, float z); 83 | void Vec3Add(const vec3_t a, const vec3_t b, vec3_t out); 84 | void Vec3Sub(const vec3_t a, const vec3_t b, vec3_t out); 85 | float Vec3Dot(const vec3_t a, const vec3_t b); 86 | float Vec3Normalize(vec3_t v); 87 | float Vec3Length(const vec3_t v); 88 | float Vec3SquareLength(const vec3_t v); 89 | void Vec3Mul(const vec3_t a, float f, vec3_t out); 90 | float Deg2Rad(float deg); 91 | float Rad2Deg(float rad); 92 | XMVECTOR Vec3ToXMVECTOR(const vec3_t v, float w); 93 | void XMVECTORToVec3(const XMVECTOR &in, vec3_t out); 94 | float ClampYaw(float yaw); 95 | float ClampPitch(float pitch); 96 | 97 | void Vec4Copy(const vec4_t in, vec4_t out); 98 | void Vec4Set(vec4_t v, float x, float y, float z, float w); 99 | void Vec4Sub(const vec4_t a, const vec4_t b, vec4_t out); 100 | void Vec4MulAdd(const vec4_t a, float f, const vec4_t b, vec4_t out); 101 | 102 | #define FOVY 70.0f 103 | #define NEAR_CLIP_PLANE 1.0f 104 | #define FAR_CLIP_PLANE 8192.0f 105 | #define VIEWPORT_CX 1024 106 | #define VIEWPORT_CY 600 107 | 108 | struct camera_s { 109 | vec3_t mPos; 110 | vec3_t mTarget; 111 | vec3_t mUp; 112 | float mFovy; 113 | float mZNear; 114 | float mZFar; 115 | }; 116 | 117 | struct frustum_plane_s { 118 | vec4_t mLeftPlane; 119 | vec4_t mRightPlane; 120 | 121 | void Setup(int viewport_width, int viewport_height, const camera_s &cam); 122 | bool CullHorizontalCircle(const vec3_t ¢er, float radius) const; 123 | }; 124 | 125 | /* 126 | ================================================================================ 127 | Vertex Format 128 | ================================================================================ 129 | */ 130 | struct vertex_pos_s { 131 | vec3_t mPosition; 132 | }; 133 | 134 | struct vertex_pos_clr_s { 135 | vec3_t mPosition; 136 | vec4_t mColor; 137 | }; 138 | 139 | struct vertex_pos_texcoord_s { 140 | vec3_t mPosition; 141 | vec2_t mTexCoord; 142 | }; 143 | 144 | #define MAX_DRAW_VERT_COUNT (1024 * 1024 * 2 * 3) // tune this 145 | #define MAX_DRAW_IDX_COUNT (1024 * 1024 * 2 * 3) // tune this 146 | #define RESTART_INDEX 0xffffffff 147 | #define MAX_PRINT_TEXT_LEN 1024 148 | 149 | /* 150 | ================================================================================ 151 | Terrain Mesh 152 | ================================================================================ 153 | */ 154 | struct mesh_s { 155 | vertex_pos_s * mVertices; 156 | int mVerticesCount; 157 | unsigned int * mIndices; 158 | int mIndicesCount; 159 | int mTriangleCount; 160 | }; 161 | 162 | /* 163 | ================================================================================ 164 | Demo 165 | ================================================================================ 166 | */ 167 | #define MAX_TERRAIN_SIZE 4097 168 | 169 | // pixel error control, tune this using arrow up / arrow down key 170 | #define DEFAILT_PIXEL_ERROR 2.0f 171 | #define MIN_PIXEL_ERROR 1.0f 172 | #define MAX_PIXEL_ERROR 4.0f 173 | 174 | // viewer movement speed, tune this using page up / page down key 175 | #define MIN_MOVE_SPEED 1.0f 176 | #define MAX_MOVE_SPEED 100.0f 177 | 178 | // viewer rotation 179 | #define MOUSE_SENSITIVITY 0.2f 180 | 181 | struct demo_info_s { 182 | double mUpdateTimeElapsed; 183 | float mMaxPixelError; 184 | }; 185 | 186 | struct test_data_s { 187 | const char_t * mHeightMap; 188 | const char_t * mColorMap; 189 | float mElevationScale; 190 | }; 191 | 192 | extern const test_data_s TEST_DATA[2]; 193 | 194 | void ToggleFlags(unsigned int &flags, unsigned int f); 195 | 196 | /* 197 | ================================================================================ 198 | Log 199 | ================================================================================ 200 | */ 201 | #define SYS_ERROR(fmt, ...) Sys_Error(__SRC_FILE__, __LINE__, fmt, __VA_ARGS__) 202 | 203 | void Sys_Error(const char_t *file, int line, const char_t *fmt, ...); 204 | 205 | /* 206 | ================================================================================ 207 | String 208 | ================================================================================ 209 | */ 210 | void Str_ExtractDirSelf(char_t *s); 211 | void Str_ExtractExeDir(const char_t *exe, char_t *dir, int dir_size); 212 | int Str_ToAnsi(const char_t *src, char * dst, int dst_chars); 213 | int Str_FrAnsi(const char *src, char_t * dst, int dst_chars); 214 | 215 | /* 216 | ================================================================================ 217 | File 218 | ================================================================================ 219 | */ 220 | int File_LoadBinary(const char_t * filename, char *buffer, int buffer_size); 221 | 222 | /* 223 | ================================================================================ 224 | Timer 225 | ================================================================================ 226 | */ 227 | void Sys_InitTimer(); 228 | double Sys_GetRelativeTime(); // seconds 229 | 230 | /* 231 | ================================================================================ 232 | Image 233 | ================================================================================ 234 | */ 235 | 236 | #define IMG_FORMAT_1BYTE_GRAY 1 237 | #define IMG_FORMAT_2BYTE_GRAY 2 238 | #define IMG_FORMAT_1BYTE_RGB 3 239 | #define IMG_FORMAT_1BYTE_RGBA 4 240 | 241 | struct image_s { 242 | int mFormat; 243 | int mCX; 244 | int mCY; 245 | void * mData; 246 | }; 247 | 248 | bool ReadPNG(const char_t *filename, image_s *image); 249 | bool SavePNG(const char_t *filename, const image_s *image); 250 | void FreeImg(image_s *image); 251 | 252 | /* 253 | ================================================================================ 254 | Input 255 | ================================================================================ 256 | */ 257 | #define IN_LBUTTON_DOWN 1 258 | #define IN_LBUTTON_UP 2 259 | #define IN_MOUSE_MOVE 3 260 | #define IN_KEY_DOWN 4 261 | #define IN_KEY_UP 5 262 | 263 | struct input_s { 264 | int mType; 265 | int mParam1; 266 | int mParam2; 267 | }; 268 | -------------------------------------------------------------------------------- /source/Terrain.cpp: -------------------------------------------------------------------------------- 1 | // Terrain.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | Terrain 8 | ================================================================================ 9 | */ 10 | Terrain::Terrain() { 11 | mCenter[0] = mCenter[1] = mCenter[2] = 0.0f; 12 | } 13 | 14 | Terrain::~Terrain() { 15 | // do nothing 16 | } 17 | 18 | bool Terrain::Init(const char_t *res_dir, int test_case, float max_pixel_error) { 19 | char_t full_filename[MAX_PATH_]; 20 | sprintf_s_(full_filename, TXT_("%s\\terrain\\%s"), res_dir, TEST_DATA[test_case].mHeightMap); 21 | 22 | image_s heights = { 0 }; 23 | 24 | if (ReadPNG(full_filename, &heights)) { 25 | if (CheckTerrainSize(heights.mCX, heights.mCY)) { 26 | height_field_s hf; 27 | hf.mHeights = (float*)malloc(sizeof(float) * heights.mCX * heights.mCY); 28 | hf.mSizeX = heights.mCX; 29 | hf.mSizeY = heights.mCY; 30 | 31 | if (heights.mFormat == IMG_FORMAT_2BYTE_GRAY) { 32 | for (int y = 0; y < heights.mCY; ++y) { 33 | unsigned short * src_row = (unsigned short*)heights.mData + y * heights.mCX; 34 | float * dst_row = hf.mHeights + (heights.mCY - y - 1) * heights.mCX; // png scanlines are ordered from top to bottom, revert y 35 | for (int x = 0; x < heights.mCX; ++x) { 36 | float f = (float)src_row[x] * TEST_DATA[test_case].mElevationScale; 37 | dst_row[x] = f; 38 | } 39 | } 40 | } 41 | else if (heights.mFormat == IMG_FORMAT_1BYTE_RGB) { 42 | for (int y = 0; y < heights.mCY; ++y) { 43 | unsigned char * src_row = (unsigned char*)heights.mData + y * heights.mCX * 3; 44 | float * dst_row = hf.mHeights + (heights.mCY - y - 1) * heights.mCX; // png scanlines are ordered from top to bottom, revert y 45 | for (int x = 0; x < heights.mCX; ++x) { 46 | unsigned char * src_pixel = src_row + x * 3; 47 | float f = (float)src_pixel[0] * TEST_DATA[test_case].mElevationScale; 48 | dst_row[x] = f; 49 | } 50 | } 51 | } 52 | else { 53 | printf("unsupported terrain height format\n"); 54 | free(hf.mHeights); 55 | FreeImg(&heights); 56 | return false; 57 | } 58 | 59 | mGeoMipmapping.Build(hf, FOVY, VIEWPORT_CX, VIEWPORT_CY, max_pixel_error); 60 | 61 | mCenter[0] = (float)(heights.mCX / 2); 62 | mCenter[1] = (float)(heights.mCY / 2); 63 | mCenter[2] = hf.mHeights[(heights.mCY / 2) * heights.mCX + heights.mCX / 2]; 64 | 65 | free(hf.mHeights); 66 | FreeImg(&heights); 67 | 68 | return true; 69 | } 70 | else { 71 | printf("wrong terrain size\n"); 72 | FreeImg(&heights); 73 | return false; 74 | } 75 | } 76 | else { 77 | return false; 78 | } 79 | } 80 | 81 | void Terrain::Shutdown() { 82 | mGeoMipmapping.Clear(); 83 | } 84 | 85 | void Terrain::GetCenter(vec3_t center) const { 86 | Vec3Copy(mCenter, center); 87 | } 88 | 89 | void Terrain::Reshape(int view_width, int view_height) { 90 | mGeoMipmapping.Reshape(view_width, view_height); 91 | } 92 | 93 | void Terrain::UpdateMaxPixelError(float max_pixel_error) { 94 | mGeoMipmapping.UpdateMaxPixelError(max_pixel_error); 95 | } 96 | 97 | void Terrain::Update(const camera_s &cam) { 98 | mGeoMipmapping.Update(cam); 99 | } 100 | 101 | const mesh_s & Terrain::GetRenderMesh() const { 102 | return mGeoMipmapping.GetRenderMesh(); 103 | } 104 | -------------------------------------------------------------------------------- /source/Terrain.h: -------------------------------------------------------------------------------- 1 | // Terrain.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | Terrain 8 | ================================================================================ 9 | */ 10 | class Terrain { 11 | public: 12 | Terrain(); 13 | ~Terrain(); 14 | 15 | bool Init(const char_t *res_dir, int test_case, float max_pixel_error); 16 | void Shutdown(); 17 | 18 | void GetCenter(vec3_t center) const; 19 | 20 | void Reshape(int view_width, int view_height); 21 | void UpdateMaxPixelError(float max_pixel_error); 22 | 23 | // update terrain geometry each frame 24 | void Update(const camera_s &cam); 25 | const mesh_s & GetRenderMesh() const; 26 | 27 | private: 28 | 29 | vec3_t mCenter; 30 | GeoMipMapping mGeoMipmapping; 31 | }; 32 | -------------------------------------------------------------------------------- /source/Viewer.cpp: -------------------------------------------------------------------------------- 1 | // Viewer.cpp 2 | 3 | #include "Precompiled.h" 4 | 5 | /* 6 | ================================================================================ 7 | Viewer 8 | ================================================================================ 9 | */ 10 | #define START_FORWARD XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f) 11 | #define START_RIGHT XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f) 12 | #define START_UP XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f) 13 | 14 | Viewer::Viewer(): 15 | mYaw(0.0f), 16 | mPitch(0.0f) 17 | { 18 | Vec3Set(mCamera.mPos, 0.0f, 0.0f, 0.0f); 19 | mCamera.mFovy = FOVY; 20 | mCamera.mZNear = NEAR_CLIP_PLANE; 21 | mCamera.mZFar = FAR_CLIP_PLANE; 22 | UpdateCameraOrientation(); 23 | } 24 | 25 | Viewer::~Viewer() { 26 | // do nothing 27 | } 28 | 29 | void Viewer::InitPos(const vec3_t pos) { 30 | Vec3Copy(pos, mCamera.mPos); 31 | UpdateCameraOrientation(); 32 | } 33 | 34 | void Viewer::Update(const movement_delta_s &delta) { 35 | mYaw += delta.mDeltaYaw; 36 | mPitch += delta.mDeltaPitch; 37 | UpdateCameraOrientation(); 38 | 39 | vec3_t delta_forward, delta_right, delta_up; 40 | Vec3Mul(mCameraForward, delta.mMoveForward * delta.mMoveSpeed * delta.mDeltaSeconds, delta_forward); 41 | Vec3Mul(mCameraRight, delta.mMoveRight * delta.mMoveSpeed * delta.mDeltaSeconds, delta_right); 42 | 43 | static const vec3_t UP = { 0.0f, 0.0f, 1.0f }; // Z direction 44 | Vec3Mul(UP, delta.mMoveUp * delta.mMoveSpeed * delta.mDeltaSeconds, delta_up); 45 | 46 | vec3_t total_delta; 47 | Vec3Add(delta_forward, delta_right, total_delta); 48 | Vec3Add(total_delta, delta_up, total_delta); 49 | 50 | Vec3Add(mCamera.mPos, total_delta, mCamera.mPos); 51 | Vec3Add(mCamera.mPos, mCameraForward, mCamera.mTarget); 52 | } 53 | 54 | void Viewer::UpdateCameraOrientation() { 55 | // clamp rotation 56 | mYaw = ClampYaw(mYaw); 57 | mPitch = ClampPitch(mPitch); 58 | 59 | // update rotation 60 | XMMATRIX yaw_matrix = XMMatrixRotationZ(Deg2Rad(mYaw)); 61 | 62 | XMVECTOR camera_forward = XMVector4Transform(START_FORWARD, yaw_matrix); 63 | XMVECTOR camera_right = XMVector4Transform(START_RIGHT, yaw_matrix); 64 | 65 | XMMATRIX pitch_matrix = XMMatrixRotationAxis(camera_right, Deg2Rad(mPitch)); 66 | 67 | camera_forward = XMVector4Transform(camera_forward, pitch_matrix); 68 | XMVECTOR camera_up = XMVector4Transform(START_UP, pitch_matrix); 69 | 70 | camera_forward = XMVector4Normalize(camera_forward); 71 | camera_right = XMVector4Normalize(camera_right); 72 | camera_up = XMVector4Normalize(camera_up); 73 | 74 | XMVECTORToVec3(camera_forward, mCameraForward); 75 | XMVECTORToVec3(camera_right, mCameraRight); 76 | XMVECTORToVec3(camera_up, mCamera.mUp); 77 | 78 | Vec3Add(mCamera.mPos, mCameraForward, mCamera.mTarget); 79 | } 80 | 81 | const camera_s & Viewer::GetCamera() const { 82 | return mCamera; 83 | } 84 | -------------------------------------------------------------------------------- /source/Viewer.h: -------------------------------------------------------------------------------- 1 | // Viewer.h 2 | 3 | #pragma once 4 | 5 | /* 6 | ================================================================================ 7 | Viewer 8 | ================================================================================ 9 | */ 10 | class Viewer { 11 | public: 12 | 13 | struct movement_delta_s { 14 | float mDeltaYaw; 15 | float mDeltaPitch; 16 | float mMoveForward; 17 | float mMoveRight; 18 | float mMoveUp; 19 | float mMoveSpeed; 20 | float mDeltaSeconds; 21 | }; 22 | 23 | Viewer(); 24 | ~Viewer(); 25 | 26 | void InitPos(const vec3_t pos); 27 | void Update(const movement_delta_s &delta); 28 | const camera_s & GetCamera() const; 29 | 30 | private: 31 | 32 | camera_s mCamera; 33 | 34 | float mYaw; 35 | float mPitch; 36 | vec3_t mCameraForward; 37 | vec3_t mCameraRight; 38 | 39 | void UpdateCameraOrientation(); 40 | }; 41 | 42 | --------------------------------------------------------------------------------