diff --git a/.gitignore b/.gitignore index 845c64ce0..0dbc751f9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,12 +6,15 @@ build-win/ cmake_build/ dependencies/ CMakeFiles/ +stk-editor/ .config/ supertuxkart-64 +data/editor data/karts data/library +data/models data/music data/sfx data/textures diff --git a/.travis.yml b/.travis.yml index 86a203378..06ef93281 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,9 @@ before_install: - sudo apt-get update -qq # Install dependencies - sudo apt-get install build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev - # Install mesa from an other repo (a newer version is required) - - sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu quantal main restricted" + # Install mesa from an other repo (a newer version is required). Quantal is not supported anymore, saucy is only supported till July 2014, + # so we try to use trusty (precise which is what traiv uses a too old mesa version which doesn't link) + - sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu trusty main restricted" - sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 3B4FE6ACC0B21F32 - sudo apt-get update -qq - sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index 725de1145..966c5efe6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,9 +124,9 @@ if(UNIX AND USE_XRANDR) endif() if(UNIX) - if(USE_CPP2011) - add_definitions("-std=c++0x") - endif() +# if(USE_CPP2011) + add_definitions("-std=gnu++0x") +# endif() endif() # OpenGL diff --git a/data/gui/custom_video_settings.stkgui b/data/gui/custom_video_settings.stkgui index 2942c4312..e5383347b 100644 --- a/data/gui/custom_video_settings.stkgui +++ b/data/gui/custom_video_settings.stkgui @@ -70,27 +70,11 @@ - - -
-
- - -
- - - -
- - -
-
-
+ +
@@ -105,7 +89,27 @@
+ + +
+ + +
+ + +
+ + + +
+ + +
+
+
@@ -136,9 +140,9 @@
- + -
diff --git a/data/models/Hammer.jpg b/data/models/Hammer.jpg deleted file mode 100644 index 23936c89c..000000000 Binary files a/data/models/Hammer.jpg and /dev/null differ diff --git a/data/models/License.txt b/data/models/License.txt deleted file mode 100644 index 7c0365972..000000000 --- a/data/models/License.txt +++ /dev/null @@ -1,82 +0,0 @@ -* plunger model, cake model, bomb model, anchor model - created by MiniBjorn (c) 2008 - released under Creative Commons Attribution-Share Alike 3.0 - [http://creativecommons.org/licenses/by-sa/3.0/] - -* bubblegum model, nitrotank-big model, nitrotank-small model, giftbox model - created by MiniBjorn (c) 2008 - released under Creative Commons Attribution-Share Alike 3.0 - [http://creativecommons.org/licenses/by-sa/3.0/] - -* banana.ac - created by horace aka thomas oppl (toppl@fh-sbg.ac.at) (c) 2008 - released under Creative Commons Attribution-Share Alike 3.0 - [http://creativecommons.org/licenses/by-sa/3.0/] - -* chest* - by MiniBjorn (c) 2010 - released under Creative Commons Attribution-Share Alike 3.0 - [http://creativecommons.org/licenses/by-sa/3.0/] - -* gplose - released under CC-BY-SA 3.0 [http://creativecommons.org/licenses/by-sa/3.0/] - oak by Julius Krischan Makowka, released un CC-BY-SA 3.0 - Tires by Thomas Oppl, released under CC-BY-SA 3.0 - scene and finishing touches by Marianne Gagnon - -* Hammer.jpg - by Marianne Gagnon, released under CC-BY-SA 3.0 - Incorporates image by Philipp Zinger, released under CCBY 3.0 - image by Louise Price, released under CC-BY 2.0 (considered a derivate work thus allowing to upgrade the license version), - image by Smoth 007, released under CC-BY-SA 2.0 (considered a derivate work thus allowing to upgrade the license version), - image by Juangonzalez64 released under the public domain - -* swatter, christmas_hat - released under CC-BY-SA 3.0 - by Funto - -* tire - based on work by Thomas Oppl, released under CC-BY-SA 3.0 - with modifications by Marianne Gagnon - -* tnt-bomb - by Fraang, released under CC-BY-SA 3.0 - -* village - released under CC-BY-SA 3.0 [http://creativecommons.org/licenses/by-sa/3.0/] - oak by Julius Krischan Makowka, released un CC-BY-SA 3.0 - mushrooms by pfunked, with modifications by Marianne Gagnon, released under CC-BY-SA 3.0 - pinos by Moser Juan José, with minor modifications by Marianne Gagnon, released under CC-BY-SA 3.0 - scene and finishing touches by Marianne Gagnon - -* shroom_color* textures by Julius Krischan Makowka, released un CC-BY-SA 3.0 - -* door.png by Marianne Gagnon, released under CC-BY-SA 3.0, based on a public domain image - from BurningWell. - -* zipper_collect - by Connor, released as Public Domain - -* rubber_ball and jump-bomb.jpg - by Samuncle, released under CC-BY-SA - -* thunderbird model - by Funto & Kinsu, released under CC-BY-SA 3.0 - -* thunderbird texture, easter egg, bomb texture - by Fraag, released under CC-BY-SA 3.0 - -* swatter-icon - by Totoplus62, released under CC-0 - -* balldimpleddark - by Hero, released under CC-BY-SA 3.0 - -* rubber_ball-icon, plunger icon, easter egg icon, cake icon, bowling ball texture and icon - by Totoplus62, released under CC-BY-SA 3.0 - -* shield-icon - by tuxfan, release under CC-BY-SA 3.0 - - -Others are GPL, by the original (super)TuxKart team diff --git a/data/models/anchor-attach-icon.png b/data/models/anchor-attach-icon.png deleted file mode 100644 index 1b053fa5e..000000000 Binary files a/data/models/anchor-attach-icon.png and /dev/null differ diff --git a/data/models/anchor-icon.png b/data/models/anchor-icon.png deleted file mode 100644 index 3ac70ee99..000000000 Binary files a/data/models/anchor-icon.png and /dev/null differ diff --git a/data/models/anchor.b3d b/data/models/anchor.b3d deleted file mode 100644 index 2142f7761..000000000 Binary files a/data/models/anchor.b3d and /dev/null differ diff --git a/data/models/anchor.png b/data/models/anchor.png deleted file mode 100644 index 58b517fbd..000000000 Binary files a/data/models/anchor.png and /dev/null differ diff --git a/data/models/ball.jpg b/data/models/ball.jpg deleted file mode 100644 index 9d073a029..000000000 Binary files a/data/models/ball.jpg and /dev/null differ diff --git a/data/models/balldimpleddark.jpg b/data/models/balldimpleddark.jpg deleted file mode 100644 index 991f58b5b..000000000 Binary files a/data/models/balldimpleddark.jpg and /dev/null differ diff --git a/data/models/banana-low.b3d b/data/models/banana-low.b3d deleted file mode 100644 index ec6ee3cae..000000000 Binary files a/data/models/banana-low.b3d and /dev/null differ diff --git a/data/models/banana.b3d b/data/models/banana.b3d deleted file mode 100644 index 90888d701..000000000 Binary files a/data/models/banana.b3d and /dev/null differ diff --git a/data/models/banana.png b/data/models/banana.png deleted file mode 100644 index f7dd34ec1..000000000 Binary files a/data/models/banana.png and /dev/null differ diff --git a/data/models/bomb-attach-icon.png b/data/models/bomb-attach-icon.png deleted file mode 100644 index d015e8ef7..000000000 Binary files a/data/models/bomb-attach-icon.png and /dev/null differ diff --git a/data/models/bomb.b3d b/data/models/bomb.b3d deleted file mode 100644 index b1da4b322..000000000 Binary files a/data/models/bomb.b3d and /dev/null differ diff --git a/data/models/bonusblock1.png b/data/models/bonusblock1.png deleted file mode 100644 index 9b451414a..000000000 Binary files a/data/models/bonusblock1.png and /dev/null differ diff --git a/data/models/bonusblock2.b3d b/data/models/bonusblock2.b3d deleted file mode 100644 index 16354c0ba..000000000 Binary files a/data/models/bonusblock2.b3d and /dev/null differ diff --git a/data/models/bowling-icon.png b/data/models/bowling-icon.png deleted file mode 100644 index 2109251ee..000000000 Binary files a/data/models/bowling-icon.png and /dev/null differ diff --git a/data/models/bowling.b3d b/data/models/bowling.b3d deleted file mode 100644 index 3de5eac90..000000000 Binary files a/data/models/bowling.b3d and /dev/null differ diff --git a/data/models/bowling.png b/data/models/bowling.png deleted file mode 100644 index 6bfbe2b82..000000000 Binary files a/data/models/bowling.png and /dev/null differ diff --git a/data/models/bronze.png b/data/models/bronze.png deleted file mode 100644 index 32a63334e..000000000 Binary files a/data/models/bronze.png and /dev/null differ diff --git a/data/models/bubblegum-icon.png b/data/models/bubblegum-icon.png deleted file mode 100644 index 637d532d3..000000000 Binary files a/data/models/bubblegum-icon.png and /dev/null differ diff --git a/data/models/bubblegum-low.b3d b/data/models/bubblegum-low.b3d deleted file mode 100644 index 4fd60cd40..000000000 Binary files a/data/models/bubblegum-low.b3d and /dev/null differ diff --git a/data/models/bubblegum-nolok-low.b3d b/data/models/bubblegum-nolok-low.b3d deleted file mode 100644 index 220b7d141..000000000 Binary files a/data/models/bubblegum-nolok-low.b3d and /dev/null differ diff --git a/data/models/bubblegum-nolok.b3d b/data/models/bubblegum-nolok.b3d deleted file mode 100644 index 474fe8353..000000000 Binary files a/data/models/bubblegum-nolok.b3d and /dev/null differ diff --git a/data/models/bubblegum.b3d b/data/models/bubblegum.b3d deleted file mode 100644 index f5d7201bc..000000000 Binary files a/data/models/bubblegum.b3d and /dev/null differ diff --git a/data/models/bubblegum.png b/data/models/bubblegum.png deleted file mode 100644 index f9eaee268..000000000 Binary files a/data/models/bubblegum.png and /dev/null differ diff --git a/data/models/bubblegum_nolok.jpg b/data/models/bubblegum_nolok.jpg deleted file mode 100644 index f34b78589..000000000 Binary files a/data/models/bubblegum_nolok.jpg and /dev/null differ diff --git a/data/models/bubblegum_shield.b3d b/data/models/bubblegum_shield.b3d deleted file mode 100644 index 00b3d5d42..000000000 Binary files a/data/models/bubblegum_shield.b3d and /dev/null differ diff --git a/data/models/bubblegum_shield.png b/data/models/bubblegum_shield.png deleted file mode 100644 index 2ebe7913c..000000000 Binary files a/data/models/bubblegum_shield.png and /dev/null differ diff --git a/data/models/bubblegum_shield_nolok.b3d b/data/models/bubblegum_shield_nolok.b3d deleted file mode 100644 index a498e97f0..000000000 Binary files a/data/models/bubblegum_shield_nolok.b3d and /dev/null differ diff --git a/data/models/bubblegum_shield_nolok.png b/data/models/bubblegum_shield_nolok.png deleted file mode 100644 index 1dde72a9d..000000000 Binary files a/data/models/bubblegum_shield_nolok.png and /dev/null differ diff --git a/data/models/cake-icon.png b/data/models/cake-icon.png deleted file mode 100644 index 86b0f5b2d..000000000 Binary files a/data/models/cake-icon.png and /dev/null differ diff --git a/data/models/cake.b3d b/data/models/cake.b3d deleted file mode 100644 index ccb7271bf..000000000 Binary files a/data/models/cake.b3d and /dev/null differ diff --git a/data/models/cake.png b/data/models/cake.png deleted file mode 100644 index c4459bf99..000000000 Binary files a/data/models/cake.png and /dev/null differ diff --git a/data/models/candy_stripe.png b/data/models/candy_stripe.png deleted file mode 100644 index 9033d5292..000000000 Binary files a/data/models/candy_stripe.png and /dev/null differ diff --git a/data/models/chest.b3d b/data/models/chest.b3d deleted file mode 100644 index 6dfc67d17..000000000 Binary files a/data/models/chest.b3d and /dev/null differ diff --git a/data/models/chest.jpg b/data/models/chest.jpg deleted file mode 100644 index f44596033..000000000 Binary files a/data/models/chest.jpg and /dev/null differ diff --git a/data/models/christmas_hat.b3d b/data/models/christmas_hat.b3d deleted file mode 100644 index 261209589..000000000 Binary files a/data/models/christmas_hat.b3d and /dev/null differ diff --git a/data/models/christmas_hat.png b/data/models/christmas_hat.png deleted file mode 100644 index 227b61076..000000000 Binary files a/data/models/christmas_hat.png and /dev/null differ diff --git a/data/models/easter_egg-icon.png b/data/models/easter_egg-icon.png deleted file mode 100644 index b3ed0fe91..000000000 Binary files a/data/models/easter_egg-icon.png and /dev/null differ diff --git a/data/models/easter_egg.b3d b/data/models/easter_egg.b3d deleted file mode 100644 index e2fd13a6a..000000000 Binary files a/data/models/easter_egg.b3d and /dev/null differ diff --git a/data/models/easter_egg_3.png b/data/models/easter_egg_3.png deleted file mode 100644 index a388e7e9a..000000000 Binary files a/data/models/easter_egg_3.png and /dev/null differ diff --git a/data/models/gift-box-low.b3d b/data/models/gift-box-low.b3d deleted file mode 100644 index c435fea23..000000000 Binary files a/data/models/gift-box-low.b3d and /dev/null differ diff --git a/data/models/gift-box.b3d b/data/models/gift-box.b3d deleted file mode 100644 index aa89d7c56..000000000 Binary files a/data/models/gift-box.b3d and /dev/null differ diff --git a/data/models/gift-box.png b/data/models/gift-box.png deleted file mode 100644 index 46dff7c9b..000000000 Binary files a/data/models/gift-box.png and /dev/null differ diff --git a/data/models/gift-loop.png b/data/models/gift-loop.png deleted file mode 100644 index 3971225fa..000000000 Binary files a/data/models/gift-loop.png and /dev/null differ diff --git a/data/models/gold.png b/data/models/gold.png deleted file mode 100644 index 72d47c3b3..000000000 Binary files a/data/models/gold.png and /dev/null differ diff --git a/data/models/jump-bomb.jpg b/data/models/jump-bomb.jpg deleted file mode 100644 index 273419d36..000000000 Binary files a/data/models/jump-bomb.jpg and /dev/null differ diff --git a/data/models/materials.xml b/data/models/materials.xml deleted file mode 100644 index 4a7f9bf9e..000000000 --- a/data/models/materials.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/models/nitrotank-big-low.b3d b/data/models/nitrotank-big-low.b3d deleted file mode 100644 index 9009158bb..000000000 Binary files a/data/models/nitrotank-big-low.b3d and /dev/null differ diff --git a/data/models/nitrotank-big.b3d b/data/models/nitrotank-big.b3d deleted file mode 100644 index 53b8032bf..000000000 Binary files a/data/models/nitrotank-big.b3d and /dev/null differ diff --git a/data/models/nitrotank-small-low.b3d b/data/models/nitrotank-small-low.b3d deleted file mode 100644 index 568bccfd8..000000000 Binary files a/data/models/nitrotank-small-low.b3d and /dev/null differ diff --git a/data/models/nitrotank-small.b3d b/data/models/nitrotank-small.b3d deleted file mode 100644 index 1afb4eead..000000000 Binary files a/data/models/nitrotank-small.b3d and /dev/null differ diff --git a/data/models/parachute-attach-icon.png b/data/models/parachute-attach-icon.png deleted file mode 100644 index cfab603ae..000000000 Binary files a/data/models/parachute-attach-icon.png and /dev/null differ diff --git a/data/models/parachute-icon.png b/data/models/parachute-icon.png deleted file mode 100644 index 10fea95a6..000000000 Binary files a/data/models/parachute-icon.png and /dev/null differ diff --git a/data/models/parachute.b3d b/data/models/parachute.b3d deleted file mode 100644 index 511f8ac42..000000000 Binary files a/data/models/parachute.b3d and /dev/null differ diff --git a/data/models/parachute.png b/data/models/parachute.png deleted file mode 100644 index a5aad3ed9..000000000 Binary files a/data/models/parachute.png and /dev/null differ diff --git a/data/models/plunger-icon.png b/data/models/plunger-icon.png deleted file mode 100644 index 382d2d4fe..000000000 Binary files a/data/models/plunger-icon.png and /dev/null differ diff --git a/data/models/plunger.b3d b/data/models/plunger.b3d deleted file mode 100644 index ce461508f..000000000 Binary files a/data/models/plunger.b3d and /dev/null differ diff --git a/data/models/plunger.png b/data/models/plunger.png deleted file mode 100644 index 4b6d928b4..000000000 Binary files a/data/models/plunger.png and /dev/null differ diff --git a/data/models/referee.xml b/data/models/referee.xml deleted file mode 100644 index 35472ebc8..000000000 --- a/data/models/referee.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - diff --git a/data/models/reset-attach-icon.png b/data/models/reset-attach-icon.png deleted file mode 100644 index 767c978f2..000000000 Binary files a/data/models/reset-attach-icon.png and /dev/null differ diff --git a/data/models/reset-button.b3d b/data/models/reset-button.b3d deleted file mode 100644 index 31093dea8..000000000 Binary files a/data/models/reset-button.b3d and /dev/null differ diff --git a/data/models/reset-button.png b/data/models/reset-button.png deleted file mode 100644 index 8d2df1ae5..000000000 Binary files a/data/models/reset-button.png and /dev/null differ diff --git a/data/models/rubber_ball-icon.png b/data/models/rubber_ball-icon.png deleted file mode 100644 index a5aee7add..000000000 Binary files a/data/models/rubber_ball-icon.png and /dev/null differ diff --git a/data/models/rubber_ball.b3d b/data/models/rubber_ball.b3d deleted file mode 100644 index 59dd3b7a8..000000000 Binary files a/data/models/rubber_ball.b3d and /dev/null differ diff --git a/data/models/shield-icon.png b/data/models/shield-icon.png deleted file mode 100644 index 41e27bc21..000000000 Binary files a/data/models/shield-icon.png and /dev/null differ diff --git a/data/models/shroom_color2.png b/data/models/shroom_color2.png deleted file mode 100644 index d217b282e..000000000 Binary files a/data/models/shroom_color2.png and /dev/null differ diff --git a/data/models/shroom_color_a.png b/data/models/shroom_color_a.png deleted file mode 100644 index bbacb578d..000000000 Binary files a/data/models/shroom_color_a.png and /dev/null differ diff --git a/data/models/silver.png b/data/models/silver.png deleted file mode 100644 index 9ec5d8d0f..000000000 Binary files a/data/models/silver.png and /dev/null differ diff --git a/data/models/stk_mod_nitroBarrel.png b/data/models/stk_mod_nitroBarrel.png deleted file mode 100644 index 5d29a7f5f..000000000 Binary files a/data/models/stk_mod_nitroBarrel.png and /dev/null differ diff --git a/data/models/stk_mod_nitroBottle.png b/data/models/stk_mod_nitroBottle.png deleted file mode 100644 index c996eef59..000000000 Binary files a/data/models/stk_mod_nitroBottle.png and /dev/null differ diff --git a/data/models/stk_mod_nitroLogo.png b/data/models/stk_mod_nitroLogo.png deleted file mode 100644 index 4dae47fbf..000000000 Binary files a/data/models/stk_mod_nitroLogo.png and /dev/null differ diff --git a/data/models/swap-icon.png b/data/models/swap-icon.png deleted file mode 100644 index 8a02cbb64..000000000 Binary files a/data/models/swap-icon.png and /dev/null differ diff --git a/data/models/swatter-icon.png b/data/models/swatter-icon.png deleted file mode 100644 index c3ff719a5..000000000 Binary files a/data/models/swatter-icon.png and /dev/null differ diff --git a/data/models/swatter.b3d b/data/models/swatter.b3d deleted file mode 100644 index 4e638c74f..000000000 Binary files a/data/models/swatter.b3d and /dev/null differ diff --git a/data/models/swatter.png b/data/models/swatter.png deleted file mode 100644 index 3782c851a..000000000 Binary files a/data/models/swatter.png and /dev/null differ diff --git a/data/models/swatter_anim2.b3d b/data/models/swatter_anim2.b3d deleted file mode 100644 index ce2995290..000000000 Binary files a/data/models/swatter_anim2.b3d and /dev/null differ diff --git a/data/models/swatter_nolok.b3d b/data/models/swatter_nolok.b3d deleted file mode 100644 index 995897fcb..000000000 Binary files a/data/models/swatter_nolok.b3d and /dev/null differ diff --git a/data/models/thunderbird.b3d b/data/models/thunderbird.b3d deleted file mode 100644 index 0dee65d10..000000000 Binary files a/data/models/thunderbird.b3d and /dev/null differ diff --git a/data/models/thunderbird.png b/data/models/thunderbird.png deleted file mode 100644 index 8b5b8439b..000000000 Binary files a/data/models/thunderbird.png and /dev/null differ diff --git a/data/models/tire.b3d b/data/models/tire.b3d deleted file mode 100644 index c18b26df7..000000000 Binary files a/data/models/tire.b3d and /dev/null differ diff --git a/data/models/tnt-bomb.png b/data/models/tnt-bomb.png deleted file mode 100644 index 15b08f261..000000000 Binary files a/data/models/tnt-bomb.png and /dev/null differ diff --git a/data/models/traffic_light_green.jpg b/data/models/traffic_light_green.jpg deleted file mode 100644 index a66b07ba4..000000000 Binary files a/data/models/traffic_light_green.jpg and /dev/null differ diff --git a/data/models/traffic_light_red.jpg b/data/models/traffic_light_red.jpg deleted file mode 100644 index bfb59316f..000000000 Binary files a/data/models/traffic_light_red.jpg and /dev/null differ diff --git a/data/models/traffic_light_yellow.jpg b/data/models/traffic_light_yellow.jpg deleted file mode 100644 index c2e7bcd54..000000000 Binary files a/data/models/traffic_light_yellow.jpg and /dev/null differ diff --git a/data/models/trophy_bronze.b3d b/data/models/trophy_bronze.b3d deleted file mode 100644 index fe5d3c29c..000000000 Binary files a/data/models/trophy_bronze.b3d and /dev/null differ diff --git a/data/models/trophy_gold.b3d b/data/models/trophy_gold.b3d deleted file mode 100644 index 88039ce82..000000000 Binary files a/data/models/trophy_gold.b3d and /dev/null differ diff --git a/data/models/trophy_silver.b3d b/data/models/trophy_silver.b3d deleted file mode 100644 index b57585d26..000000000 Binary files a/data/models/trophy_silver.b3d and /dev/null differ diff --git a/data/models/warning.b3d b/data/models/warning.b3d deleted file mode 100644 index 0364480cf..000000000 Binary files a/data/models/warning.b3d and /dev/null differ diff --git a/data/models/warning.png b/data/models/warning.png deleted file mode 100644 index fcc25de1c..000000000 Binary files a/data/models/warning.png and /dev/null differ diff --git a/data/models/zipper.b3d b/data/models/zipper.b3d deleted file mode 100644 index ed7e7ac82..000000000 Binary files a/data/models/zipper.b3d and /dev/null differ diff --git a/data/models/zipper.png b/data/models/zipper.png deleted file mode 100644 index de30dbfe8..000000000 Binary files a/data/models/zipper.png and /dev/null differ diff --git a/data/models/zipper_collect.png b/data/models/zipper_collect.png deleted file mode 100644 index d5e4f3c96..000000000 Binary files a/data/models/zipper_collect.png and /dev/null differ diff --git a/data/shaders/displace.frag b/data/shaders/displace.frag index 84fe29b60..eca0e7189 100644 --- a/data/shaders/displace.frag +++ b/data/shaders/displace.frag @@ -42,14 +42,6 @@ void main() // Fade according to distance to cam float fade = 1.0 - smoothstep(1.0, 100.0, camdist); - // Fade according to distance from the edges - const float mindist = 0.1; - fade *= smoothstep(0.0, mindist, uv_bis.x) * smoothstep(0.0, mindist, uv_bis.y) * - (1.0 - smoothstep(1.0 - mindist, 1.0, uv_bis.x)) * - (1.0 - smoothstep(1.0 - mindist, 1.0, uv_bis.y)); - - offset *= 50.0 * fade * maxlen; - vec4 shiftval; shiftval.r = step(offset.x, 0.0) * -offset.x; shiftval.g = step(0.0, offset.x) * offset.x; diff --git a/data/shaders/grass_pass.vert b/data/shaders/grass_pass.vert index fa52d4c7f..fc3e83ed7 100644 --- a/data/shaders/grass_pass.vert +++ b/data/shaders/grass_pass.vert @@ -1,7 +1,23 @@ -uniform vec3 windDir; -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 TransposeInverseModelView; +#ifdef UBO_DISABLED +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform mat4 InverseViewMatrix; +uniform mat4 InverseProjectionMatrix; +#else +layout (std140) uniform MatrixesData +{ + mat4 ViewMatrix; + mat4 ProjectionMatrix; + mat4 InverseViewMatrix; + mat4 InverseProjectionMatrix; + mat4 ShadowViewProjMatrixes[4]; + vec2 screen; +}; +#endif +uniform vec3 windDir; +uniform mat4 ModelMatrix; +uniform mat4 InverseModelMatrix; #if __VERSION__ >= 330 layout(location = 0) in vec3 Position; @@ -20,7 +36,9 @@ out vec2 uv; void main() { - uv = Texcoord; - nor = (TransposeInverseModelView * vec4(Normal, 1.)).xyz; - gl_Position = ModelViewProjectionMatrix * vec4(Position + windDir * Color.r, 1.); + uv = Texcoord; + mat4 ModelViewProjectionMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix; + mat4 TransposeInverseModelView = transpose(InverseModelMatrix * InverseViewMatrix); + nor = (TransposeInverseModelView * vec4(Normal, 1.)).xyz; + gl_Position = ModelViewProjectionMatrix * vec4(Position + windDir * Color.r, 1.); } diff --git a/data/shaders/grass_pass2.frag b/data/shaders/grass_pass2.frag index 0ad58609a..55aeecf59 100644 --- a/data/shaders/grass_pass2.frag +++ b/data/shaders/grass_pass2.frag @@ -1,8 +1,24 @@ +#ifdef UBO_DISABLED +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform mat4 InverseViewMatrix; +uniform mat4 InverseProjectionMatrix; +uniform vec2 screen; +#else +layout (std140) uniform MatrixesData +{ + mat4 ViewMatrix; + mat4 ProjectionMatrix; + mat4 InverseViewMatrix; + mat4 InverseProjectionMatrix; + mat4 ShadowViewProjMatrixes[4]; + vec2 screen; +}; +#endif + uniform sampler2D Albedo; uniform vec3 SunDir; -uniform mat4 invproj; uniform sampler2D dtex; -uniform vec2 screen; in vec3 nor; in vec2 uv; @@ -16,7 +32,7 @@ void main(void) float z = texture(dtex, texc).x; vec4 xpos = 2.0 * vec4(texc, z, 1.0) - 1.0f; - xpos = invproj * xpos; + xpos = InverseProjectionMatrix * xpos; xpos /= xpos.w; vec3 eyedir = normalize(xpos.xyz); diff --git a/data/shaders/instanciedgrassshadow.vert b/data/shaders/instanciedgrassshadow.vert new file mode 100644 index 000000000..92c21af65 --- /dev/null +++ b/data/shaders/instanciedgrassshadow.vert @@ -0,0 +1,50 @@ +layout (std140) uniform MatrixesData +{ + mat4 ViewMatrix; + mat4 ProjectionMatrix; + mat4 InverseViewMatrix; + mat4 InverseProjectionMatrix; + mat4 ShadowViewProjMatrixes[4]; +}; +uniform vec3 windDir; +#if __VERSION__ >= 330 +layout(location = 0) in vec3 Position; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec2 Texcoord; + +layout(location = 7) in vec3 Origin; +layout(location = 8) in vec3 Orientation; +layout(location = 9) in vec3 Scale; +#else +in vec3 Position; +in vec4 Color; +in vec2 Texcoord; + +in vec3 Origin; +in vec3 Orientation; +in vec3 Scale; +#endif + +#ifdef VSLayer +out vec2 uv; +#else +out vec2 tc; +out int layerId; +#endif + +mat4 getWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); +mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation, vec3 scale); + +void main(void) +{ + mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale); +#ifdef VSLayer + gl_Layer = gl_InstanceID & 3; + gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * vec4(Position + windDir * Color.r, 1.); + uv = Texcoord; +#else + layerId = gl_InstanceID & 3; + gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * vec4(Position + windDir * Color.r, 1.); + tc = Texcoord; +#endif +} \ No newline at end of file diff --git a/data/shaders/rh.frag b/data/shaders/rh.frag index 6b1a45c16..ed760b4ab 100644 --- a/data/shaders/rh.frag +++ b/data/shaders/rh.frag @@ -60,7 +60,7 @@ void main(void) vec2 uv = RHuv + offset * 0.01; // Get world position and normal from the RSM sample - float depth = texture2D(dtex, uv).z; + float depth = texture(dtex, uv).z; vec4 RSMPos = inverse(RSMMatrix) * (2. * vec4(uv, depth, 1.) - 1.); RSMPos /= RSMPos.w; vec3 RSMAlbedo = texture(ctex, uv).xyz; diff --git a/data/shaders/rsm.vert b/data/shaders/rsm.vert index 5ed3b9ad4..69846d811 100644 --- a/data/shaders/rsm.vert +++ b/data/shaders/rsm.vert @@ -8,11 +8,17 @@ uniform mat4 TextureMatrix = 0., 0., 1., 0., 0., 0., 0., 1.); - +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 1) in vec3 Normal; layout(location = 2) in vec4 Color; layout(location = 3) in vec2 Texcoord; +#else +in vec3 Position; +in vec3 Normal; +in vec4 Color; +in vec2 Texcoord; +#endif out vec3 nor; out vec2 uv; diff --git a/data/shaders/shadow.vert b/data/shaders/shadow.vert index d1212e7ea..d7f6316e6 100644 --- a/data/shaders/shadow.vert +++ b/data/shaders/shadow.vert @@ -9,8 +9,13 @@ layout (std140) uniform MatrixesData uniform mat4 ModelMatrix; +#if __VERSION__ >= 330 layout(location = 0) in vec3 Position; layout(location = 3) in vec2 Texcoord; +#else +in vec3 Position; +in vec2 Texcoord; +#endif #ifdef VSLayer out vec2 uv; diff --git a/data/shaders/shadow_grass.vert b/data/shaders/shadow_grass.vert new file mode 100644 index 000000000..7b1ce0caf --- /dev/null +++ b/data/shaders/shadow_grass.vert @@ -0,0 +1,41 @@ +layout (std140) uniform MatrixesData +{ + mat4 ViewMatrix; + mat4 ProjectionMatrix; + mat4 InverseViewMatrix; + mat4 InverseProjectionMatrix; + mat4 ShadowViewProjMatrixes[4]; +}; + +uniform mat4 ModelMatrix; +uniform vec3 windDir; + +#if __VERSION__ >= 330 +layout(location = 0) in vec3 Position; +layout(location = 2) in vec4 Color; +layout(location = 3) in vec2 Texcoord; +#else +in vec3 Position; +in vec4 Color; +in vec2 Texcoord; +#endif + +#ifdef VSLayer +out vec2 uv; +#else +out vec2 tc; +out int layerId; +#endif + +void main(void) +{ +#ifdef VSLayer + gl_Layer = gl_InstanceID & 3; + uv = Texcoord; + gl_Position = ShadowViewProjMatrixes[gl_Layer] * ModelMatrix * vec4(Position + windDir * Color.r, 1.); +#else + layerId = gl_InstanceID & 3; + tc = Texcoord; + gl_Position = ShadowViewProjMatrixes[layerId] * ModelMatrix * vec4(Position + windDir * Color.r, 1.); +#endif +} diff --git a/data/shaders/splatting.frag b/data/shaders/splatting.frag index 8fb96d066..ede2b6a47 100644 --- a/data/shaders/splatting.frag +++ b/data/shaders/splatting.frag @@ -41,7 +41,7 @@ void main() { vec4 splatted = splatting.r * detail0 + splatting.g * detail1 + splatting.b * detail2 + - (1.0 - splatting.r - splatting.g - splatting.b) * detail3; + max(0., (1.0 - splatting.r - splatting.g - splatting.b)) * detail3; vec2 tc = gl_FragCoord.xy / screen; vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz; diff --git a/data/shaders/ssao.frag b/data/shaders/ssao.frag index 445de5388..c31e34f0b 100644 --- a/data/shaders/ssao.frag +++ b/data/shaders/ssao.frag @@ -26,7 +26,7 @@ out float AO; const float sigma = 1.; const float tau = 7.; -const float beta = 0.001; +const float beta = 0.002; const float epsilon = .00001; const float radius = 1.; const float k = 1.5; @@ -38,8 +38,8 @@ const float invSamples = 1. / SAMPLES; vec3 getXcYcZc(int x, int y, float zC) { // We use perspective symetric projection matrix hence P(0,2) = P(1, 2) = 0 - float xC= (1. - 2 * (float(x) + 0.5) / screen.x) * zC / ProjectionMatrix[0][0]; - float yC= (1. + 2 * (float(y) + 0.5) / screen.y) * zC / ProjectionMatrix[1][1]; + float xC= (2 * (float(x)) / screen.x - 1.) * zC / ProjectionMatrix[0][0]; + float yC= (2 * (float(y)) / screen.y - 1.) * zC / ProjectionMatrix[1][1]; return vec3(xC, yC, zC); } @@ -53,7 +53,7 @@ void main(void) // get the normal of current fragment vec3 ddx = dFdx(FragPos); vec3 ddy = dFdy(FragPos); - vec3 norm = -normalize(cross(ddy, ddx)); + vec3 norm = normalize(cross(ddy, ddx)); float r = radius / FragPos.z; float phi = 3. * (x ^ y) + x * y; diff --git a/src/config/device_config.cpp b/src/config/device_config.cpp index 32db91569..488550389 100644 --- a/src/config/device_config.cpp +++ b/src/config/device_config.cpp @@ -19,6 +19,7 @@ #include #include "config/device_config.hpp" +#include "utils/log.hpp" #include using namespace irr; @@ -226,7 +227,7 @@ bool DeviceConfig::deserializeAction(irr::io::IrrXMLReader* xml) // Never hurts to check ;) if (xml == NULL) { - fprintf(stderr, "Error: null pointer (DeviceConfig::deserializeAction)\n"); + Log::error("DeviceConfig", "Null pointer (DeviceConfig::deserializeAction)"); return false; } @@ -243,8 +244,8 @@ bool DeviceConfig::deserializeAction(irr::io::IrrXMLReader* xml) } if(binding_id==-1) { - printf("WARNING: DeviceConfig::deserializeAction : action '%s' is unknown\n", - name_string); + Log::warn("DeviceConfig", "DeviceConfig::deserializeAction : action '%s' is unknown.", + name_string); return false; } @@ -349,23 +350,15 @@ GamepadConfig::GamepadConfig(irr::io::IrrXMLReader* xml) : DeviceConfig( DEVICE_ { const char* name_string = xml->getAttributeValue("name"); if(name_string == NULL) - { - printf("ERROR: Unnamed joystick in config file\n"); - } + Log::error("DeviceConfig", "Unnamed joystick in config file."); else - { m_name = name_string; - } const char* enabled_string = xml->getAttributeValue("enabled"); if (enabled_string != NULL) - { m_enabled = (strcmp(enabled_string, "true") == 0); - } else - { m_enabled = true; - } m_plugged = 0; setDefaultBinds(); diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 3cf9171cb..5294ef234 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -713,8 +713,8 @@ bool UserConfig::loadConfig() // add back the code previously there that upgraded the config file to the new // format instead of overwriting it. - GUIEngine::showMessage( _("Your config file was too old, so it was deleted and a new one will be created."), 10.0f); - printf("Your config file was too old, so it was deleted and a new one will be created."); + GUIEngine::showMessage(_("Your config file was too old, so it was deleted and a new one will be created."), 10.0f); + Log::info("UserConfig", "Your config file was too old, so it was deleted and a new one will be created."); delete root; return false; diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 70a57c36f..2ebed145a 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -205,8 +205,8 @@ void Camera::setupCamera() break; default: if(UserConfigParams::logMisc()) - fprintf(stderr, "Incorrect number of players: '%d' - assuming 1.\n", - race_manager->getNumLocalPlayers()); + Log::warn("Camera", "Incorrect number of players: '%d' - assuming 1.", + race_manager->getNumLocalPlayers()); m_viewport = core::recti(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); diff --git a/src/graphics/camera.hpp b/src/graphics/camera.hpp index e9555ea7f..125bc439f 100644 --- a/src/graphics/camera.hpp +++ b/src/graphics/camera.hpp @@ -155,10 +155,9 @@ private: m_type = EC_AHEAD_OF_KART; else { - fprintf(stderr, - "Invalid camera type '%s' - camera is ignored.\n", - s.c_str()); - return false; + Log::warn("Camera", "Invalid camera type '%s' - camera is ignored.", + s.c_str()); + return false; } node.get("xyz", &m_position); node.get("distance", &m_distance2); diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index d83c5c3ea..7b82dcb97 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -1932,8 +1932,9 @@ void IrrDriver::update(float dt) // ================================= if (!m_device->run()) { - GUIEngine::cleanUp(); - GUIEngine::deallocate(); + // Don't bother cleaning up GUI, has no use and may result in crashes + //GUIEngine::cleanUp(); + //GUIEngine::deallocate(); main_loop->abort(); return; } diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 29baf0534..69909bce2 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -70,7 +70,6 @@ enum STKRenderingPass SOLID_LIT_PASS, TRANSPARENT_PASS, GLOW_PASS, - DISPLACEMENT_PASS, SHADOW_PASS, PASS_COUNT, }; @@ -353,8 +352,6 @@ private: std::vector m_forcedbloom; - std::vector m_displacing; - std::vector m_background; STKRenderingPass m_phase; @@ -380,7 +377,6 @@ private: void renderGlow(std::vector& glows); void renderSSAO(); void renderLights(unsigned pointlightCount); - void renderDisplacement(); void renderShadowsDebug(); void doScreenShot(); public: @@ -668,12 +664,6 @@ public: // ------------------------------------------------------------------------ const std::vector &getForcedBloom() const { return m_forcedbloom; } // ------------------------------------------------------------------------ - void clearDisplacingNodes() { m_displacing.clear(); } - // ------------------------------------------------------------------------ - const std::vector &getDisplacingNodes() const { return m_displacing; } - // ------------------------------------------------------------------------ - void addDisplacingNode(scene::ISceneNode * const n) { m_displacing.push_back(n); } - // ------------------------------------------------------------------------ void clearBackgroundNodes() { m_background.clear(); } // ------------------------------------------------------------------------ void addBackgroundNode(scene::ISceneNode * const n) { m_background.push_back(n); } diff --git a/src/graphics/material_manager.cpp b/src/graphics/material_manager.cpp index a5fea5f95..544cf635a 100644 --- a/src/graphics/material_manager.cpp +++ b/src/graphics/material_manager.cpp @@ -239,7 +239,7 @@ bool MaterialManager::pushTempMaterial(const XMLNode *root, if(!node) { // We don't have access to the filename at this stage anymore :( - fprintf(stderr, "Unknown node in material.xml file\n"); + Log::warn("MaterialManager", "Unknown node in material.xml file."); continue; } try @@ -249,7 +249,7 @@ bool MaterialManager::pushTempMaterial(const XMLNode *root, catch(std::exception& e) { // The message contains a '%s' for the filename - fprintf(stderr, e.what(), filename.c_str()); + Log::warn("MaterialManager", e.what(), filename.c_str()); } } // for igetNumNodes)( return true; diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp index bfc66d6b3..8bf4d0ada 100644 --- a/src/graphics/particle_emitter.cpp +++ b/src/graphics/particle_emitter.cpp @@ -581,7 +581,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type) } default: { - fprintf(stderr, "[ParticleEmitter] Unknown shape\n"); + Log::error("ParticleEmitter", "Unknown shape"); return; } } diff --git a/src/graphics/particle_kind.cpp b/src/graphics/particle_kind.cpp index e23b4e92e..d332ceacf 100644 --- a/src/graphics/particle_kind.cpp +++ b/src/graphics/particle_kind.cpp @@ -100,7 +100,7 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2 } else { - fprintf(stderr, "[ParticleKind] main node has unknown value for attribute 'emitter'\n"); + Log::warn("ParticleKind", " main node has unknown value for attribute 'emitter'."); m_shape = EMITTER_POINT; } @@ -254,8 +254,8 @@ Material* ParticleKind::getMaterial() const } else { - fprintf(stderr, "[ParticleKind] WARNING: particle image '%s' does not appear in the list of " - "currently known materials\n", m_material_file.c_str()); + Log::warn("ParticleKind", "Particle image '%s' does not appear in the list of " + "currently known materials.", m_material_file.c_str()); return NULL; } } diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 9993087d8..90bf81d42 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -266,10 +266,6 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po { glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO); - PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00); - renderSolidFirstPass(); - PROFILER_POP_CPU_MARKER(); - // Shadows { PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90); @@ -283,6 +279,12 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po PROFILER_POP_CPU_MARKER(); } + PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00); + renderSolidFirstPass(); + PROFILER_POP_CPU_MARKER(); + + + // Lights { PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00); @@ -319,8 +321,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po } PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF); - if (!SkyboxTextures.empty()) - renderSkybox(camnode); + renderSkybox(camnode); PROFILER_POP_CPU_MARKER(); if (getRH()) @@ -379,13 +380,6 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po return; } - // Render displacement - { - PROFILER_PUSH_CPU_MARKER("- Displacement", 0x00, 0x00, 0xFF); - ScopedGPUTimer Timer(getGPUTimer(Q_DISPLACEMENT)); - renderDisplacement(); - PROFILER_POP_CPU_MARKER(); - } // Ensure that no object will be drawn after that by using invalid pass irr_driver->setPhase(PASS_COUNT); } @@ -504,363 +498,6 @@ void IrrDriver::computeSunVisibility() } } -void IrrDriver::renderSolidFirstPass() -{ - m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind(); - glClearColor(0., 0., 0., 0.); - glDepthMask(GL_TRUE); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); - GroupedFPSM::reset(); - GroupedFPSM::reset(); - GroupedFPSM::reset(); - GroupedFPSM::reset(); - m_scene_manager->drawAll(scene::ESNRP_SOLID); - - if (!UserConfigParams::m_dynamic_lights) - return; - - { - ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1)); - glUseProgram(MeshShader::ObjectPass1Shader::Program); - glBindVertexArray(getVAO(video::EVT_STANDARD)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - GLMesh &mesh = *GroupedFPSM::MeshSet[i]; - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0); - } - - glBindVertexArray(getVAO(video::EVT_2TCOORDS)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - GLMesh &mesh = *GroupedFPSM::MeshSet[i]; - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0); - } - - glUseProgram(MeshShader::ObjectRefPass1Shader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - const GLMesh &mesh = *GroupedFPSM::MeshSet[i]; - if (mesh.VAOType != video::EVT_STANDARD) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - continue; - } - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], GroupedFPSM::MeshSet[i]->TextureMatrix, 0); - } - glUseProgram(MeshShader::NormalMapShader::Program); - glBindVertexArray(getVAO(EVT_TANGENTS)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - const GLMesh &mesh = *GroupedFPSM::MeshSet[i]; - assert(mesh.VAOType == video::EVT_TANGENTS); - assert(mesh.textures[1]); - compressTexture(mesh.textures[1], false); - setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - compressTexture(mesh.textures[0], true); - setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0, 1); - } - } -} - -template -void renderMeshes2ndPass(std::vector &meshes, const std::vector &MVPMatrixes) -{ - glUseProgram(Shader::Program); - glBindVertexArray(getVAO(VertexType)); - for (unsigned i = 0; i < meshes.size(); i++) - { - GLMesh &mesh = *meshes[i]; - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - if (mesh.VAOType != VertexType) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - continue; - } - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - draw(mesh, MVPMatrixes[i], mesh.TextureMatrix); - } -} - -void IrrDriver::renderSolidSecondPass() -{ - SColor clearColor(0, 150, 150, 150); - if (World::getWorld() != NULL) - clearColor = World::getWorld()->getClearColor(); - - glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f, - clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f); - glClear(GL_COLOR_BUFFER_BIT); - - if (UserConfigParams::m_dynamic_lights) - glDepthMask(GL_FALSE); - else - { - glDepthMask(GL_TRUE); - glClear(GL_DEPTH_BUFFER_BIT); - } - - irr_driver->setPhase(SOLID_LIT_PASS); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - GroupedSM::reset(); - GroupedSM::reset(); - GroupedSM::reset(); - GroupedSM::reset(); - GroupedSM::reset(); - GroupedSM::reset(); - GroupedSM::reset(); - setTexture(0, m_rtts->getRenderTarget(RTT_TMP1), GL_NEAREST, GL_NEAREST); - setTexture(1, m_rtts->getRenderTarget(RTT_TMP2), GL_NEAREST, GL_NEAREST); - setTexture(2, m_rtts->getRenderTarget(RTT_HALF1_R), GL_LINEAR, GL_LINEAR); - - { - ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2)); - - m_scene_manager->drawAll(scene::ESNRP_SOLID); - - renderMeshes2ndPass(GroupedSM::MeshSet, GroupedSM::MVPSet); - renderMeshes2ndPass(GroupedSM::MeshSet, GroupedSM::MVPSet); - renderMeshes2ndPass(GroupedSM::MeshSet, GroupedSM::MVPSet); - - glUseProgram(MeshShader::SphereMapShader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - { - const GLMesh &mesh = *GroupedSM::MeshSet[i]; - assert(mesh.VAOType == EVT_STANDARD); - compressTexture(mesh.textures[0], true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, GroupedSM::MVPSet[i], GroupedSM::TIMVSet[i], irr_driver->getSceneManager()->getAmbientLight()); - } - - glUseProgram(MeshShader::SplattingShader::Program); - glBindVertexArray(getVAO(EVT_2TCOORDS)); - for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawSplatting(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i]); - - glUseProgram(MeshShader::ObjectUnlitShader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - { - const GLMesh &mesh = *GroupedSM::MeshSet[i]; - assert(mesh.VAOType == EVT_STANDARD); - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - draw(mesh, GroupedSM::MVPSet[i]); - } - - glUseProgram(MeshShader::DetailledObjectPass2Shader::Program); - glBindVertexArray(getVAO(EVT_2TCOORDS)); - for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - { - GLMesh &mesh = *GroupedSM::MeshSet[i]; - assert(mesh.VAOType == EVT_2TCOORDS); - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - if (!mesh.textures[1]) - { -#ifdef DEBUG - Log::error("Materials", "No detail/lightmap texture provided for detail/lightmap material."); -#endif - mesh.textures[1] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - } - compressTexture(mesh.textures[1], true); - setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, GroupedSM::MVPSet[i]); - } - } -} - -void IrrDriver::renderTransparent() -{ - irr_driver->setPhase(TRANSPARENT_PASS); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glDisable(GL_CULL_FACE); - TransparentMeshes::reset(); - TransparentMeshes::reset(); - m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT); - - glBindVertexArray(getVAO(EVT_STANDARD)); - - if (World::getWorld() && World::getWorld()->isFogEnabled()) - { - const Track * const track = World::getWorld()->getTrack(); - - // This function is only called once per frame - thus no need for setters. - const float fogmax = track->getFogMax(); - const float startH = track->getFogStartHeight(); - const float endH = track->getFogEndHeight(); - const float start = track->getFogStart(); - const float end = track->getFogEnd(); - const video::SColor tmpcol = track->getFogColor(); - - core::vector3df col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - glUseProgram(MeshShader::TransparentFogShader::Program); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - { - GLMesh &mesh = *TransparentMeshes::MeshSet[i]; - if (mesh.VAOType != EVT_STANDARD) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to fog + transparent blend (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - glBindVertexArray(getVAO(mesh.VAOType)); - } - - - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); - if (mesh.VAOType != EVT_STANDARD) - glBindVertexArray(getVAO(EVT_STANDARD)); - } - glBlendFunc(GL_ONE, GL_ONE); - for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - { - GLMesh &mesh = *TransparentMeshes::MeshSet[i]; - if (mesh.VAOType != EVT_STANDARD) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - glBindVertexArray(getVAO(mesh.VAOType)); - } - glBindVertexArray(getVAO(mesh.VAOType)); - - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); - if (mesh.VAOType != EVT_STANDARD) - glBindVertexArray(getVAO(EVT_STANDARD)); - } - } - else - { - glUseProgram(MeshShader::TransparentShader::Program); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - { - GLMesh &mesh = *TransparentMeshes::MeshSet[i]; - if (mesh.VAOType != EVT_STANDARD) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - glBindVertexArray(getVAO(mesh.VAOType)); - } - glBindVertexArray(getVAO(mesh.VAOType)); - if (!mesh.textures[0]) - mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, 0); - if (mesh.VAOType != EVT_STANDARD) - glBindVertexArray(getVAO(EVT_STANDARD)); - } - - glBlendFunc(GL_ONE, GL_ONE); - for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - { - const GLMesh &mesh = *TransparentMeshes::MeshSet[i]; - if (mesh.VAOType != EVT_STANDARD) - { -#ifdef DEBUG - Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); -#endif - glBindVertexArray(getVAO(mesh.VAOType)); - } - glBindVertexArray(getVAO(mesh.VAOType)); - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, 0); - if (mesh.VAOType != EVT_STANDARD) - glBindVertexArray(getVAO(EVT_STANDARD)); - } - } -} - void IrrDriver::renderParticles() { glDepthMask(GL_FALSE); @@ -1063,66 +700,7 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz delete []tmp; } -void IrrDriver::renderShadows() -{ - irr_driver->setPhase(SHADOW_PASS); - glDisable(GL_BLEND); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.5, 0.); - m_rtts->getShadowFBO().Bind(); - glClear(GL_DEPTH_BUFFER_BIT); - glDrawBuffer(GL_NONE); - glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO); - - m_scene_manager->drawAll(scene::ESNRP_SOLID); - - glUseProgram(MeshShader::ShadowShader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); - glBindVertexArray(getVAO(EVT_2TCOORDS)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); - glBindVertexArray(getVAO(EVT_TANGENTS)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); - - glUseProgram(MeshShader::RefShadowShader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - drawShadowRef(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); - - glDisable(GL_POLYGON_OFFSET_FILL); - - if (!UserConfigParams::m_gi) - return; - - m_rtts->getRSM().Bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glUseProgram(MeshShader::RSMShader::Program); - glBindVertexArray(getVAO(EVT_STANDARD)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - const GLMesh mesh = *GroupedFPSM::MeshSet[i]; - if (!mesh.textures[0]) - continue; - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, rsm_matrix, GroupedFPSM::MVPSet[i], 0); - } - glBindVertexArray(getVAO(EVT_2TCOORDS)); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - { - const GLMesh mesh = *GroupedFPSM::MeshSet[i]; - if (!mesh.textures[0]) - continue; - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, rsm_matrix, GroupedFPSM::MVPSet[i], 0); - } -} static void renderWireFrameFrustrum(float *tmp, unsigned i) { @@ -1211,704 +789,4 @@ void IrrDriver::renderGlow(std::vector& glows) m_rtts->getFBO(FBO_COLORS).Bind(); m_post_processing->renderGlow(m_rtts->getRenderTarget(RTT_QUARTER1)); glDisable(GL_STENCIL_TEST); -} - -// ---------------------------------------------------------------------------- - -static LightShader::PointLightInfo PointLightsInfo[MAXLIGHT]; - -static void renderPointLights(unsigned count) -{ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - - glUseProgram(LightShader::PointLightShader::Program); - glBindVertexArray(LightShader::PointLightShader::vao); - glBindBuffer(GL_ARRAY_BUFFER, LightShader::PointLightShader::vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(LightShader::PointLightInfo), PointLightsInfo); - - setTexture(0, irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), GL_NEAREST, GL_NEAREST); - setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); - LightShader::PointLightShader - ::setUniforms(core::vector2df(float(UserConfigParams::m_width), - float(UserConfigParams::m_height) ), - 200, 0, 1); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); -} - -unsigned IrrDriver::UpdateLightsInfo(scene::ICameraSceneNode * const camnode, float dt) -{ - const u32 lightcount = m_lights.size(); - const core::vector3df &campos = camnode->getAbsolutePosition(); - - std::vector BucketedLN[15]; - for (unsigned int i = 0; i < lightcount; i++) - { - if (!m_lights[i]->isPointLight()) - { - m_lights[i]->render(); - continue; - } - const core::vector3df &lightpos = (m_lights[i]->getAbsolutePosition() - campos); - unsigned idx = (unsigned)(lightpos.getLength() / 10); - if (idx > 14) - idx = 14; - BucketedLN[idx].push_back(m_lights[i]); - } - - unsigned lightnum = 0; - - for (unsigned i = 0; i < 15; i++) - { - for (unsigned j = 0; j < BucketedLN[i].size(); j++) - { - if (++lightnum >= MAXLIGHT) - { - LightNode* light_node = BucketedLN[i].at(j); - light_node->setEnergyMultiplier(0.0f); - } - else - { - LightNode* light_node = BucketedLN[i].at(j); - - float em = light_node->getEnergyMultiplier(); - if (em < 1.0f) - { - light_node->setEnergyMultiplier(std::min(1.0f, em + dt)); - } - - const core::vector3df &pos = light_node->getAbsolutePosition(); - PointLightsInfo[lightnum].posX = pos.X; - PointLightsInfo[lightnum].posY = pos.Y; - PointLightsInfo[lightnum].posZ = pos.Z; - - PointLightsInfo[lightnum].energy = light_node->getEffectiveEnergy(); - - const core::vector3df &col = light_node->getColor(); - PointLightsInfo[lightnum].red = col.X; - PointLightsInfo[lightnum].green = col.Y; - PointLightsInfo[lightnum].blue = col.Z; - - // Light radius - PointLightsInfo[lightnum].radius = light_node->getRadius(); - } - } - if (lightnum > MAXLIGHT) - { - irr_driver->setLastLightBucketDistance(i * 10); - break; - } - } - - lightnum++; - return lightnum; -} - -void IrrDriver::renderLights(unsigned pointlightcount) -{ - //RH - if (UserConfigParams::m_gi) - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH)); - glDisable(GL_BLEND); - m_rtts->getRH().Bind(); - glUseProgram(FullScreenShader::RadianceHintsConstructionShader::Program); - glBindVertexArray(FullScreenShader::RadianceHintsConstructionShader::vao); - setTexture(0, m_rtts->getRSM().getRTT()[0], GL_LINEAR, GL_LINEAR); - setTexture(1, m_rtts->getRSM().getRTT()[1], GL_LINEAR, GL_LINEAR); - setTexture(2, m_rtts->getRSM().getDepthTexture(), GL_LINEAR, GL_LINEAR); - FullScreenShader::RadianceHintsConstructionShader::setUniforms(rsm_matrix, rh_matrix, rh_extend, 0, 1, 2); - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32); - } - - for (unsigned i = 0; i < sun_ortho_matrix.size(); i++) - sun_ortho_matrix[i] *= getInvViewMatrix(); - m_rtts->getFBO(FBO_COMBINED_TMP1_TMP2).Bind(); - if (!UserConfigParams::m_dynamic_lights) - glClearColor(.5, .5, .5, .5); - glClear(GL_COLOR_BUFFER_BIT); - if (!UserConfigParams::m_dynamic_lights) - return; - - m_rtts->getFBO(FBO_TMP1_WITH_DS).Bind(); - if (UserConfigParams::m_gi) - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI)); - m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]); - } - - if (SkyboxCubeMap) - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP)); - m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff); - } - m_rtts->getFBO(FBO_COMBINED_TMP1_TMP2).Bind(); - - if (World::getWorld() && World::getWorld()->getTrack()->hasShadows() && SkyboxCubeMap) - irr_driver->getSceneManager()->setAmbientLight(SColor(0, 0, 0, 0)); - - // Render sunlight if and only if track supports shadow - if (!World::getWorld() || World::getWorld()->getTrack()->hasShadows()) - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN)); - if (World::getWorld() && UserConfigParams::m_shadows) - m_post_processing->renderShadowedSunlight(sun_ortho_matrix, m_rtts->getShadowDepthTex()); - else - m_post_processing->renderSunlight(); - } - { - ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS)); - renderPointLights(MIN2(pointlightcount, MAXLIGHT)); - } -} - -void IrrDriver::renderSSAO() -{ - m_rtts->getFBO(FBO_SSAO).Bind(); - glClearColor(1., 1., 1., 1.); - glClear(GL_COLOR_BUFFER_BIT); - m_post_processing->renderSSAO(); - // Blur it to reduce noise. - FrameBuffer::Blit(m_rtts->getFBO(FBO_SSAO), m_rtts->getFBO(FBO_HALF1_R), GL_COLOR_BUFFER_BIT, GL_LINEAR); - m_post_processing->renderGaussian17TapBlur(irr_driver->getFBO(FBO_HALF1_R), irr_driver->getFBO(FBO_HALF2_R)); - -} - -static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z) -{ - switch (face) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - x = 1.; - y = -i; - z = -j; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - x = -1.; - y = -i; - z = j; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - x = j; - y = 1.; - z = i; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - x = j; - y = -1; - z = -i; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - x = j; - y = -i; - z = 1; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - x = -j; - y = -i; - z = -1; - break; - } - - float norm = sqrt(x * x + y * y + z * z); - x /= norm, y /= norm, z /= norm; - return; -} - -static void getYml(GLenum face, size_t width, size_t height, - float *Y00, - float *Y1minus1, float *Y10, float *Y11, - float *Y2minus2, float *Y2minus1, float *Y20, float *Y21, float *Y22) -{ - for (unsigned i = 0; i < width; i++) - { - for (unsigned j = 0; j < height; j++) - { - float x, y, z; - float fi = float(i), fj = float(j); - fi /= width, fj /= height; - fi = 2 * fi - 1, fj = 2 * fj - 1; - getXYZ(face, fi, fj, x, y, z); - - // constant part of Ylm - float c00 = 0.282095f; - float c1minus1 = 0.488603f; - float c10 = 0.488603f; - float c11 = 0.488603f; - float c2minus2 = 1.092548f; - float c2minus1 = 1.092548f; - float c21 = 1.092548f; - float c20 = 0.315392f; - float c22 = 0.546274f; - - size_t idx = i * height + j; - - Y00[idx] = c00; - Y1minus1[idx] = c1minus1 * y; - Y10[idx] = c10 * z; - Y11[idx] = c11 * x; - Y2minus2[idx] = c2minus2 * x * y; - Y2minus1[idx] = c2minus1 * y * z; - Y21[idx] = c21 * x * z; - Y20[idx] = c20 * (3 * z * z - 1); - Y22[idx] = c22 * (x * x - y * y); - } - } -} - -static float getTexelValue(unsigned i, unsigned j, size_t width, size_t height, float *Coeff, float *Y00, float *Y1minus1, float *Y10, float *Y11, - float *Y2minus2, float * Y2minus1, float * Y20, float *Y21, float *Y22) -{ - float d = sqrt((float)(i * i + j * j + 1)); - float solidangle = 1.; - size_t idx = i * height + j; - float reconstructedVal = Y00[idx] * Coeff[0]; - reconstructedVal += Y1minus1[i * height + j] * Coeff[1] + Y10[i * height + j] * Coeff[2] + Y11[i * height + j] * Coeff[3]; - reconstructedVal += Y2minus2[idx] * Coeff[4] + Y2minus1[idx] * Coeff[5] + Y20[idx] * Coeff[6] + Y21[idx] * Coeff[7] + Y22[idx] * Coeff[8]; - reconstructedVal /= solidangle; - return MAX2(255.0f * reconstructedVal, 0.f); -} - -static void unprojectSH(float *output[], size_t width, size_t height, - float *Y00[], - float *Y1minus1[], float *Y10[], float *Y11[], - float *Y2minus2[], float *Y2minus1[], float * Y20[],float *Y21[], float *Y22[], - float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff) -{ - for (unsigned face = 0; face < 6; face++) - { - for (unsigned i = 0; i < width; i++) - { - for (unsigned j = 0; j < height; j++) - { - float fi = float(i), fj = float(j); - fi /= width, fj /= height; - fi = 2 * fi - 1, fj = 2 * fj - 1; - - output[face][4 * height * i + 4 * j + 2] = getTexelValue(i, j, width, height, - redSHCoeff, - Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); - output[face][4 * height * i + 4 * j + 1] = getTexelValue(i, j, width, height, - greenSHCoeff, - Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); - output[face][4 * height * i + 4 * j] = getTexelValue(i, j, width, height, - blueSHCoeff, - Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); - } - } - } -} - -static void projectSH(float *color[], size_t width, size_t height, - float *Y00[], - float *Y1minus1[], float *Y10[], float *Y11[], - float *Y2minus2[], float *Y2minus1[], float * Y20[], float *Y21[], float *Y22[], - float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff - ) -{ - for (unsigned i = 0; i < 9; i++) - { - blueSHCoeff[i] = 0; - greenSHCoeff[i] = 0; - redSHCoeff[i] = 0; - } - float wh = float(width * height); - for (unsigned face = 0; face < 6; face++) - { - for (unsigned i = 0; i < width; i++) - { - for (unsigned j = 0; j < height; j++) - { - size_t idx = i * height + j; - float fi = float(i), fj = float(j); - fi /= width, fj /= height; - fi = 2 * fi - 1, fj = 2 * fj - 1; - - - float d = sqrt(fi * fi + fj * fj + 1); - - // Constant obtained by projecting unprojected ref values - float solidangle = 2.75f / (wh * pow(d, 1.5f)); - // pow(., 2.2) to convert from srgb - float b = pow(color[face][4 * height * i + 4 * j ] / 255.f, 2.2f); - float g = pow(color[face][4 * height * i + 4 * j + 1] / 255.f, 2.2f); - float r = pow(color[face][4 * height * i + 4 * j + 2] / 255.f, 2.2f); - - assert(b >= 0.); - - blueSHCoeff[0] += b * Y00[face][idx] * solidangle; - blueSHCoeff[1] += b * Y1minus1[face][idx] * solidangle; - blueSHCoeff[2] += b * Y10[face][idx] * solidangle; - blueSHCoeff[3] += b * Y11[face][idx] * solidangle; - blueSHCoeff[4] += b * Y2minus2[face][idx] * solidangle; - blueSHCoeff[5] += b * Y2minus1[face][idx] * solidangle; - blueSHCoeff[6] += b * Y20[face][idx] * solidangle; - blueSHCoeff[7] += b * Y21[face][idx] * solidangle; - blueSHCoeff[8] += b * Y22[face][idx] * solidangle; - - greenSHCoeff[0] += g * Y00[face][idx] * solidangle; - greenSHCoeff[1] += g * Y1minus1[face][idx] * solidangle; - greenSHCoeff[2] += g * Y10[face][idx] * solidangle; - greenSHCoeff[3] += g * Y11[face][idx] * solidangle; - greenSHCoeff[4] += g * Y2minus2[face][idx] * solidangle; - greenSHCoeff[5] += g * Y2minus1[face][idx] * solidangle; - greenSHCoeff[6] += g * Y20[face][idx] * solidangle; - greenSHCoeff[7] += g * Y21[face][idx] * solidangle; - greenSHCoeff[8] += g * Y22[face][idx] * solidangle; - - - redSHCoeff[0] += r * Y00[face][idx] * solidangle; - redSHCoeff[1] += r * Y1minus1[face][idx] * solidangle; - redSHCoeff[2] += r * Y10[face][idx] * solidangle; - redSHCoeff[3] += r * Y11[face][idx] * solidangle; - redSHCoeff[4] += r * Y2minus2[face][idx] * solidangle; - redSHCoeff[5] += r * Y2minus1[face][idx] * solidangle; - redSHCoeff[6] += r * Y20[face][idx] * solidangle; - redSHCoeff[7] += r * Y21[face][idx] * solidangle; - redSHCoeff[8] += r * Y22[face][idx] * solidangle; - } - } - } -} - -static void displayCoeff(float *SHCoeff) -{ - printf("L00:%f\n", SHCoeff[0]); - printf("L1-1:%f, L10:%f, L11:%f\n", SHCoeff[1], SHCoeff[2], SHCoeff[3]); - printf("L2-2:%f, L2-1:%f, L20:%f, L21:%f, L22:%f\n", SHCoeff[4], SHCoeff[5], SHCoeff[6], SHCoeff[7], SHCoeff[8]); -} - -// Only for 9 coefficients -static void testSH(unsigned char *color[6], size_t width, size_t height, - float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff) -{ - float *Y00[6]; - float *Y1minus1[6]; - float *Y10[6]; - float *Y11[6]; - float *Y2minus2[6]; - float *Y2minus1[6]; - float *Y20[6]; - float *Y21[6]; - float *Y22[6]; - - float *testoutput[6]; - for (unsigned i = 0; i < 6; i++) - { - testoutput[i] = new float[width * height * 4]; - for (unsigned j = 0; j < width * height; j++) - { - testoutput[i][4 * j ] = float(0xFF & color[i][4 * j]); - testoutput[i][4 * j + 1] = float(0xFF & color[i][4 * j + 1]); - testoutput[i][4 * j + 2] = float(0xFF & color[i][4 * j + 2]); - } - } - - for (unsigned face = 0; face < 6; face++) - { - Y00[face] = new float[width * height]; - Y1minus1[face] = new float[width * height]; - Y10[face] = new float[width * height]; - Y11[face] = new float[width * height]; - Y2minus2[face] = new float[width * height]; - Y2minus1[face] = new float[width * height]; - Y20[face] = new float[width * height]; - Y21[face] = new float[width * height]; - Y22[face] = new float[width * height]; - - getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, width, height, Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); - } - -/* blueSHCoeff[0] = 0.54, - blueSHCoeff[1] = .6, blueSHCoeff[2] = -.27, blueSHCoeff[3] = .01, - blueSHCoeff[4] = -.12, blueSHCoeff[5] = -.47, blueSHCoeff[6] = -.15, blueSHCoeff[7] = .14, blueSHCoeff[8] = -.3; - greenSHCoeff[0] = .44, - greenSHCoeff[1] = .35, greenSHCoeff[2] = -.18, greenSHCoeff[3] = -.06, - greenSHCoeff[4] = -.05, greenSHCoeff[5] = -.22, greenSHCoeff[6] = -.09, greenSHCoeff[7] = .21, greenSHCoeff[8] = -.05; - redSHCoeff[0] = .79, - redSHCoeff[1] = .39, redSHCoeff[2] = -.34, redSHCoeff[3] = -.29, - redSHCoeff[4] = -.11, redSHCoeff[5] = -.26, redSHCoeff[6] = -.16, redSHCoeff[7] = .56, redSHCoeff[8] = .21; - - printf("Blue:\n"); - displayCoeff(blueSHCoeff); - printf("Green:\n"); - displayCoeff(greenSHCoeff); - printf("Red:\n"); - displayCoeff(redSHCoeff);*/ - - projectSH(testoutput, width, height, - Y00, - Y1minus1, Y10, Y11, - Y2minus2, Y2minus1, Y20, Y21, Y22, - blueSHCoeff, greenSHCoeff, redSHCoeff - ); - - //printf("Blue:\n"); - //displayCoeff(blueSHCoeff); - //printf("Green:\n"); - //displayCoeff(greenSHCoeff); - //printf("Red:\n"); - //displayCoeff(redSHCoeff); - - - - // Convolute in frequency space -/* float A0 = 3.141593; - float A1 = 2.094395; - float A2 = 0.785398; - blueSHCoeff[0] *= A0; - greenSHCoeff[0] *= A0; - redSHCoeff[0] *= A0; - for (unsigned i = 0; i < 3; i++) - { - blueSHCoeff[1 + i] *= A1; - greenSHCoeff[1 + i] *= A1; - redSHCoeff[1 + i] *= A1; - } - for (unsigned i = 0; i < 5; i++) - { - blueSHCoeff[4 + i] *= A2; - greenSHCoeff[4 + i] *= A2; - redSHCoeff[4 + i] *= A2; - } - - - unprojectSH(testoutput, width, height, - Y00, - Y1minus1, Y10, Y11, - Y2minus2, Y2minus1, Y20, Y21, Y22, - blueSHCoeff, greenSHCoeff, redSHCoeff - );*/ - - -/* printf("Blue:\n"); - displayCoeff(blueSHCoeff); - printf("Green:\n"); - displayCoeff(greenSHCoeff); - printf("Red:\n"); - displayCoeff(redSHCoeff); - - printf("\nAfter projection\n\n");*/ - - - - for (unsigned i = 0; i < 6; i++) - { - for (unsigned j = 0; j < width * height; j++) - { - color[i][4 * j ] = char(MIN2(testoutput[i][4 * j], 255)); - color[i][4 * j + 1] = char(MIN2(testoutput[i][4 * j + 1], 255)); - color[i][4 * j + 2] = char(MIN2(testoutput[i][4 * j + 2], 255)); - } - } - - for (unsigned face = 0; face < 6; face++) - { - delete[] testoutput[face]; - delete[] Y00[face]; - delete[] Y1minus1[face]; - delete[] Y10[face]; - delete[] Y11[face]; - } -} - -/** Generate an opengl cubemap texture from 6 2d textures. - Out of legacy the sequence of textures maps to : - - 1st texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Y - - 2nd texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - - 3rd texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_X - - 4th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_X - - 5th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - - 6th texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Z -* \param textures sequence of 6 textures. -*/ -GLuint generateCubeMapFromTextures(const std::vector &textures) -{ - GLuint result; - glGenTextures(1, &result); - - unsigned w = 0, h = 0; - for (unsigned i = 0; i < 6; i++) - { - w = MAX2(w, textures[i]->getOriginalSize().Width); - h = MAX2(h, textures[i]->getOriginalSize().Height); - } - - const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 }; - char *rgba[6]; - for (unsigned i = 0; i < 6; i++) - rgba[i] = new char[w * h * 4]; - for (unsigned i = 0; i < 6; i++) - { - unsigned idx = texture_permutation[i]; - - video::IImage* image = irr_driver->getVideoDriver()->createImageFromData( - textures[idx]->getColorFormat(), - textures[idx]->getSize(), - textures[idx]->lock(), - false - ); - textures[idx]->unlock(); - - image->copyToScaling(rgba[i], w, h); - image->drop(); - - glBindTexture(GL_TEXTURE_CUBE_MAP, result); - if (UserConfigParams::m_texture_compression) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); - else - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); - } - for (unsigned i = 0; i < 6; i++) - delete[] rgba[i]; - return result; -} - -void IrrDriver::generateSkyboxCubemap() -{ - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - SkyboxCubeMap = generateCubeMapFromTextures(SkyboxTextures); - const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 }; - - if (SphericalHarmonicsTextures.size() == 6) - { - unsigned sh_w = 0, sh_h = 0; - for (unsigned i = 0; i < 6; i++) - { - sh_w = MAX2(sh_w, SphericalHarmonicsTextures[i]->getOriginalSize().Width); - sh_h = MAX2(sh_h, SphericalHarmonicsTextures[i]->getOriginalSize().Height); - } - - unsigned char *sh_rgba[6]; - for (unsigned i = 0; i < 6; i++) - sh_rgba[i] = new unsigned char[sh_w * sh_h * 4]; - for (unsigned i = 0; i < 6; i++) - { - unsigned idx = texture_permutation[i]; - - video::IImage* image = getVideoDriver()->createImageFromData( - SphericalHarmonicsTextures[idx]->getColorFormat(), - SphericalHarmonicsTextures[idx]->getSize(), - SphericalHarmonicsTextures[idx]->lock(), - false - ); - SphericalHarmonicsTextures[idx]->unlock(); - - image->copyToScaling(sh_rgba[i], sh_w, sh_h); - image->drop(); - } - - testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff); - - for (unsigned i = 0; i < 6; i++) - delete[] sh_rgba[i]; - } - else - { - int sh_w = 16; - int sh_h = 16; - - const video::SColorf& ambientf = irr_driver->getSceneManager()->getAmbientLight(); - video::SColor ambient = ambientf.toSColor(); - - unsigned char *sh_rgba[6]; - for (unsigned i = 0; i < 6; i++) - { - sh_rgba[i] = new unsigned char[sh_w * sh_h * 4]; - - for (int j = 0; j < sh_w * sh_h * 4; j+=4) - { - sh_rgba[i][j] = ambient.getBlue(); - sh_rgba[i][j + 1] = ambient.getGreen(); - sh_rgba[i][j + 2] = ambient.getRed(); - sh_rgba[i][j + 3] = 255; - } - } - - testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff); - - for (unsigned i = 0; i < 6; i++) - delete[] sh_rgba[i]; - } - - /*for (unsigned i = 0; i < 6; i++) - { - glBindTexture(GL_TEXTURE_CUBE_MAP, ConvolutedSkyboxCubeMap); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); - } - - glBindTexture(GL_TEXTURE_CUBE_MAP, 0);*/ -} - -void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera) -{ - if (!SkyboxCubeMap) - generateSkyboxCubemap(); - glBindVertexArray(MeshShader::SkyboxShader::cubevao); - glDisable(GL_CULL_FACE); - assert(SkyboxTextures.size() == 6); - - core::matrix4 translate; - translate.setTranslation(camera->getAbsolutePosition()); - - // Draw the sky box between the near and far clip plane - const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f; - core::matrix4 scale; - scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance)); - core::matrix4 transform = translate * scale; - core::matrix4 invtransform; - transform.getInverse(invtransform); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, SkyboxCubeMap); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glUseProgram(MeshShader::SkyboxShader::Program); - MeshShader::SkyboxShader::setUniforms(transform, - core::vector2df(float(UserConfigParams::m_width), - float(UserConfigParams::m_height)), - 0); - glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0); - glBindVertexArray(0); -} - -// ---------------------------------------------------------------------------- - -void IrrDriver::renderDisplacement() -{ - irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind(); - glClear(GL_COLOR_BUFFER_BIT); - irr_driver->getFBO(FBO_DISPLACE).Bind(); - glClear(GL_COLOR_BUFFER_BIT); - - DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE); - cb->update(); - - const int displacingcount = m_displacing.size(); - irr_driver->setPhase(DISPLACEMENT_PASS); - glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_BLEND); - glClear(GL_STENCIL_BUFFER_BIT); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - glBindVertexArray(getVAO(EVT_2TCOORDS)); - for (int i = 0; i < displacingcount; i++) - { - m_scene_manager->setCurrentRendertime(scene::ESNRP_TRANSPARENT); - m_displacing[i]->render(); - } - - irr_driver->getFBO(FBO_COLORS).Bind(); - glStencilFunc(GL_EQUAL, 1, 0xFF); - m_post_processing->renderPassThrough(m_rtts->getRenderTarget(RTT_DISPLACE)); - glDisable(GL_STENCIL_TEST); -} +} \ No newline at end of file diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp new file mode 100644 index 000000000..20ee1d760 --- /dev/null +++ b/src/graphics/render_geometry.cpp @@ -0,0 +1,486 @@ +#include "graphics/irr_driver.hpp" + +#include "config/user_config.hpp" +#include "graphics/callbacks.hpp" +#include "graphics/camera.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/lens_flare.hpp" +#include "graphics/light.hpp" +#include "graphics/lod_node.hpp" +#include "graphics/material_manager.hpp" +#include "graphics/particle_kind_manager.hpp" +#include "graphics/per_camera_node.hpp" +#include "graphics/post_processing.hpp" +#include "graphics/referee.hpp" +#include "graphics/rtts.hpp" +#include "graphics/screenquad.hpp" +#include "graphics/shaders.hpp" +#include "graphics/stkmeshscenenode.hpp" +#include "graphics/stkinstancedscenenode.hpp" +#include "graphics/wind.hpp" +#include "io/file_manager.hpp" +#include "items/item.hpp" +#include "items/item_manager.hpp" +#include "modes/world.hpp" +#include "physics/physics.hpp" +#include "tracks/track.hpp" +#include "utils/constants.hpp" +#include "utils/helpers.hpp" +#include "utils/log.hpp" +#include "utils/profiler.hpp" + +#include + + +template +void draw(const GLMesh *mesh, uniforms... Args) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh->PrimitiveType; + GLenum itype = mesh->IndexType; + size_t count = mesh->IndexCount; + + Shader::setUniforms(Args...); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh->vaoOffset, mesh->vaoBaseVertex); +} + + +template +void draw(const T *Shader, const GLMesh *mesh, uniforms... Args) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh->PrimitiveType; + GLenum itype = mesh->IndexType; + size_t count = mesh->IndexCount; + + Shader->setUniforms(Args...); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh->vaoOffset, mesh->vaoBaseVertex); +} + +template +struct unroll_args_instance +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + unroll_args_instance::template exec(Shader, t, std::get(t), args...); + } +}; + +template<> +struct unroll_args_instance<0> +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + draw(Shader, args...); + } +}; + +template +void apply_instance(const T *Shader, const std::tuple &arg) +{ + unroll_args_instance >::value >::template exec(Shader, arg); +} + +template +struct custom_unroll_args; + +template<> +struct custom_unroll_args<> +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + draw(Shader, std::get<0>(t), args...); + } +}; + +template +struct custom_unroll_args +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + custom_unroll_args::template exec(Shader, t, std::get(t), args...); + } +}; + + +template +void renderMeshes1stPass(const std::vector > &TexUnits, std::vector > &meshes) +{ + glUseProgram(Shader::getInstance()->Program); + glBindVertexArray(getVAO(VertexType)); + for (unsigned i = 0; i < meshes.size(); i++) + { + GLMesh &mesh = *(std::get<0>(meshes[i])); + for (unsigned j = 0; j < TexUnits.size(); j++) + { + if (!mesh.textures[j]) + mesh.textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + compressTexture(mesh.textures[j], TexUnits[j].second); + setTexture(TexUnits[j].first, getTextureGLuint(mesh.textures[j]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + } + if (mesh.VAOType != VertexType) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + continue; + } + custom_unroll_args::template exec(Shader::getInstance(), meshes[i]); + } +} + +void IrrDriver::renderSolidFirstPass() +{ + m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind(); + glClearColor(0., 0., 0., 0.); + glDepthMask(GL_TRUE); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glEnable(GL_CULL_FACE); + irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); + ListMatDefault::Arguments.clear(); + ListMatAlphaRef::Arguments.clear(); + ListMatSphereMap::Arguments.clear(); + ListMatDetails::Arguments.clear(); + ListMatUnlit::Arguments.clear(); + ListMatNormalMap::Arguments.clear(); + ListMatGrass::Arguments.clear(); + ListMatSplatting::Arguments.clear(); + m_scene_manager->drawAll(scene::ESNRP_SOLID); + + if (!UserConfigParams::m_dynamic_lights) + return; + + { + ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1)); + renderMeshes1stPass({ { MeshShader::ObjectPass1Shader::getInstance()->TU_tex, true } }, ListMatDefault::Arguments); + renderMeshes1stPass({ { MeshShader::ObjectPass1Shader::getInstance()->TU_tex, true } }, ListMatSphereMap::Arguments); + renderMeshes1stPass({ { MeshShader::ObjectPass1Shader::getInstance()->TU_tex, true } }, ListMatUnlit::Arguments); + renderMeshes1stPass({ { MeshShader::ObjectPass1Shader::getInstance()->TU_tex, true } }, ListMatDetails::Arguments); + renderMeshes1stPass({ { MeshShader::ObjectPass1Shader::getInstance()->TU_tex, true } }, ListMatSplatting::Arguments); + renderMeshes1stPass({ { MeshShader::ObjectRefPass1Shader::getInstance()->TU_tex, true } }, ListMatAlphaRef::Arguments); + renderMeshes1stPass({ { MeshShader::GrassPass1Shader::getInstance()->TU_tex, true } }, ListMatGrass::Arguments); + renderMeshes1stPass({ { MeshShader::NormalMapShader::getInstance()->TU_glossy, true }, { MeshShader::NormalMapShader::getInstance()->TU_normalmap, false } }, ListMatNormalMap::Arguments); + } +} + +template +void renderMeshes2ndPass(const std::vector > &TexUnits, std::vector > &meshes) +{ + glUseProgram(Shader::getInstance()->Program); + glBindVertexArray(getVAO(VertexType)); + for (unsigned i = 0; i < meshes.size(); i++) + { + GLMesh &mesh = *(std::get<0>(meshes[i])); + for (unsigned j = 0; j < TexUnits.size(); j++) + { + if (!mesh.textures[j]) + mesh.textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + compressTexture(mesh.textures[j], TexUnits[j].second); + setTexture(TexUnits[j].first, getTextureGLuint(mesh.textures[j]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + } + + if (mesh.VAOType != VertexType) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + continue; + } + custom_unroll_args::template exec(Shader::getInstance(), meshes[i]); + } +} + +void IrrDriver::renderSolidSecondPass() +{ + SColor clearColor(0, 150, 150, 150); + if (World::getWorld() != NULL) + clearColor = World::getWorld()->getClearColor(); + + glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f, + clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f); + glClear(GL_COLOR_BUFFER_BIT); + + if (UserConfigParams::m_dynamic_lights) + glDepthMask(GL_FALSE); + else + { + glDepthMask(GL_TRUE); + glClear(GL_DEPTH_BUFFER_BIT); + } + + irr_driver->setPhase(SOLID_LIT_PASS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + setTexture(0, m_rtts->getRenderTarget(RTT_TMP1), GL_NEAREST, GL_NEAREST); + setTexture(1, m_rtts->getRenderTarget(RTT_TMP2), GL_NEAREST, GL_NEAREST); + setTexture(2, m_rtts->getRenderTarget(RTT_HALF1_R), GL_LINEAR, GL_LINEAR); + + { + ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2)); + + m_scene_manager->drawAll(scene::ESNRP_SOLID); + + renderMeshes2ndPass({ { MeshShader::ObjectPass2Shader::getInstance()->TU_Albedo, true } }, ListMatDefault::Arguments); + renderMeshes2ndPass({ { MeshShader::ObjectRefPass2Shader::getInstance()->TU_Albedo, true } }, ListMatAlphaRef::Arguments); + renderMeshes2ndPass({ { MeshShader::SphereMapShader::getInstance()->TU_tex, true } }, ListMatSphereMap::Arguments); + renderMeshes2ndPass({ { MeshShader::DetailledObjectPass2Shader::getInstance()->TU_Albedo, true }, { MeshShader::DetailledObjectPass2Shader::getInstance()->TU_detail, true } }, ListMatDetails::Arguments); + renderMeshes2ndPass({ { MeshShader::GrassPass2Shader::getInstance()->TU_Albedo, true } }, ListMatGrass::Arguments); + renderMeshes2ndPass({ { MeshShader::ObjectUnlitShader::getInstance()->TU_tex, true } }, ListMatUnlit::Arguments); + renderMeshes2ndPass({ { 8, true }, { MeshShader::SplattingShader::getInstance()->TU_tex_layout, false }, { MeshShader::SplattingShader::getInstance()->TU_tex_detail0, true }, { MeshShader::SplattingShader::getInstance()->TU_tex_detail1, true }, { MeshShader::SplattingShader::getInstance()->TU_tex_detail2, true }, { MeshShader::SplattingShader::getInstance()->TU_tex_detail3, true } }, ListMatSplatting::Arguments); + renderMeshes2ndPass({ { MeshShader::ObjectPass2Shader::getInstance()->TU_Albedo, true } }, ListMatNormalMap::Arguments); + } +} + +static video::ITexture *displaceTex = 0; + +void IrrDriver::renderTransparent() +{ + irr_driver->setPhase(TRANSPARENT_PASS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glDisable(GL_CULL_FACE); + ListBlendTransparent::Arguments.clear(); + ListAdditiveTransparent::Arguments.clear(); + ListBlendTransparentFog::Arguments.clear(); + ListAdditiveTransparentFog::Arguments.clear(); + ListDisplacement::Arguments.clear(); + m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT); + + glBindVertexArray(getVAO(EVT_STANDARD)); + + if (World::getWorld() && World::getWorld()->isFogEnabled()) + { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + renderMeshes2ndPass({ { MeshShader::TransparentFogShader::getInstance()->TU_tex, true } }, ListBlendTransparentFog::Arguments); + glBlendFunc(GL_ONE, GL_ONE); + renderMeshes2ndPass({ { MeshShader::TransparentFogShader::getInstance()->TU_tex, true } }, ListAdditiveTransparentFog::Arguments); + } + else + { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + renderMeshes2ndPass({ { MeshShader::TransparentShader::getInstance()->TU_tex, true } }, ListBlendTransparent::Arguments); + glBlendFunc(GL_ONE, GL_ONE); + renderMeshes2ndPass({ { MeshShader::TransparentShader::getInstance()->TU_tex, true } }, ListAdditiveTransparent::Arguments); + } + + if (!UserConfigParams::m_dynamic_lights) + return; + + // Render displacement nodes + irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind(); + glClear(GL_COLOR_BUFFER_BIT); + irr_driver->getFBO(FBO_DISPLACE).Bind(); + glClear(GL_COLOR_BUFFER_BIT); + + DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE); + cb->update(); + + glEnable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + glClear(GL_STENCIL_BUFFER_BIT); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glBindVertexArray(getVAO(EVT_2TCOORDS)); + // Generate displace mask + // Use RTT_TMP4 as displace mask + irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind(); + for (unsigned i = 0; i < ListDisplacement::Arguments.size(); i++) + { + const GLMesh &mesh = *(std::get<0>(ListDisplacement::Arguments[i])); + const core::matrix4 &AbsoluteTransformation = std::get<1>(ListDisplacement::Arguments[i]); + if (mesh.VAOType != video::EVT_2TCOORDS) + { +#ifdef DEBUG + Log::error("Materials", "Displacement has wrong vertex type"); +#endif + continue; + } + + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + glUseProgram(MeshShader::DisplaceMaskShaderInstance->Program); + MeshShader::DisplaceMaskShaderInstance->setUniforms(AbsoluteTransformation); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); + } + + irr_driver->getFBO(FBO_DISPLACE).Bind(); + if (!displaceTex) + displaceTex = irr_driver->getTexture(FileManager::TEXTURE, "displace.png"); + for (unsigned i = 0; i < ListDisplacement::Arguments.size(); i++) + { + const GLMesh &mesh = *(std::get<0>(ListDisplacement::Arguments[i])); + const core::matrix4 &AbsoluteTransformation = std::get<1>(ListDisplacement::Arguments[i]); + if (mesh.VAOType != video::EVT_2TCOORDS) + continue; + + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + // Render the effect + setTexture(MeshShader::DisplaceShaderInstance->TU_displacement_tex, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true); + setTexture(MeshShader::DisplaceShaderInstance->TU_mask_tex, irr_driver->getRenderTargetTexture(RTT_TMP1), GL_LINEAR, GL_LINEAR, true); + setTexture(MeshShader::DisplaceShaderInstance->TU_color_tex, irr_driver->getRenderTargetTexture(RTT_COLOR), GL_LINEAR, GL_LINEAR, true); + setTexture(MeshShader::DisplaceShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR, true); + glUseProgram(MeshShader::DisplaceShaderInstance->Program); + MeshShader::DisplaceShaderInstance->setUniforms(AbsoluteTransformation, + core::vector2df(cb->getDirX(), cb->getDirY()), + core::vector2df(cb->getDir2X(), cb->getDir2Y())); + + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); + } + + irr_driver->getFBO(FBO_COLORS).Bind(); + glStencilFunc(GL_EQUAL, 1, 0xFF); + m_post_processing->renderPassThrough(m_rtts->getRenderTarget(RTT_DISPLACE)); + glDisable(GL_STENCIL_TEST); + +} + +template +void drawShadow(const T *Shader, const GLMesh *mesh, uniforms... Args) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh->PrimitiveType; + GLenum itype = mesh->IndexType; + size_t count = mesh->IndexCount; + + Shader->setUniforms(Args...); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh->vaoOffset, 4, mesh->vaoBaseVertex); +} + +template +struct shadow_custom_unroll_args; + +template<> +struct shadow_custom_unroll_args<> +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + drawShadow(Shader, std::get<0>(t), args...); + } +}; + +template +struct shadow_custom_unroll_args +{ + template + static void exec(const T *Shader, const std::tuple &t, Args... args) + { + shadow_custom_unroll_args::template exec(Shader, t, std::get(t), args...); + } +}; + +template +void renderShadow(const T *Shader, const std::vector TextureUnits, const std::vector >&t) +{ + glUseProgram(Shader->Program); + glBindVertexArray(getVAO(VertexType)); + for (unsigned i = 0; i < t.size(); i++) + { + const GLMesh *mesh = std::get<0>(t[i]); + for (unsigned j = 0; j < TextureUnits.size(); j++) + { + compressTexture(mesh->textures[j], true); + setTexture(TextureUnits[j], getTextureGLuint(mesh->textures[j]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + } + + shadow_custom_unroll_args::template exec(Shader, t[i]); + } +} + +template +void drawRSM(const core::matrix4 & rsm_matrix, const std::vector TextureUnits, const std::vector >&t) +{ + glUseProgram(MeshShader::RSMShader::Program); + glBindVertexArray(getVAO(VertexType)); + for (unsigned i = 0; i < t.size(); i++) + { + GLMesh *mesh = std::get<0>(t[i]); + for (unsigned j = 0; j < TextureUnits.size(); j++) + { + if (!mesh->textures[j]) + mesh->textures[j] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + compressTexture(mesh->textures[j], true); + setTexture(TextureUnits[j], getTextureGLuint(mesh->textures[j]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + } + draw(mesh, rsm_matrix, std::get<1>(t[i])); + } +} + +void IrrDriver::renderShadows() +{ + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.5, 0.); + m_rtts->getShadowFBO().Bind(); + glClear(GL_DEPTH_BUFFER_BIT); + glDrawBuffer(GL_NONE); + + irr_driver->setPhase(SHADOW_PASS); + ListMatDefault::Arguments.clear(); + ListMatAlphaRef::Arguments.clear(); + ListMatSphereMap::Arguments.clear(); + ListMatDetails::Arguments.clear(); + ListMatUnlit::Arguments.clear(); + ListMatNormalMap::Arguments.clear(); + ListMatGrass::Arguments.clear(); + ListMatSplatting::Arguments.clear(); + m_scene_manager->drawAll(scene::ESNRP_SOLID); + + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatDefault::Arguments); + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatSphereMap::Arguments); + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatUnlit::Arguments); + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatDetails::Arguments); + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatSplatting::Arguments); + renderShadow(MeshShader::ShadowShaderInstance, {}, ListMatNormalMap::Arguments); + renderShadow(MeshShader::RefShadowShaderInstance, { MeshShader::RefShadowShaderInstance->TU_tex }, ListMatAlphaRef::Arguments); + renderShadow(MeshShader::GrassShadowShaderInstance, { MeshShader::GrassShadowShaderInstance->TU_tex }, ListMatGrass::Arguments); + + glDisable(GL_POLYGON_OFFSET_FILL); + + if (!UserConfigParams::m_gi) + return; + + m_rtts->getRSM().Bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + drawRSM(rsm_matrix, { MeshShader::RSMShader::TU_tex }, ListMatDefault::Arguments); + drawRSM(rsm_matrix, { MeshShader::RSMShader::TU_tex }, ListMatSphereMap::Arguments); + drawRSM(rsm_matrix, { MeshShader::RSMShader::TU_tex }, ListMatUnlit::Arguments); + drawRSM(rsm_matrix, { MeshShader::RSMShader::TU_tex }, ListMatDetails::Arguments); + drawRSM(rsm_matrix, { MeshShader::RSMShader::TU_tex }, ListMatSplatting::Arguments); +} diff --git a/src/graphics/render_lighting.cpp b/src/graphics/render_lighting.cpp new file mode 100644 index 000000000..c74e57a2b --- /dev/null +++ b/src/graphics/render_lighting.cpp @@ -0,0 +1,199 @@ +#include "graphics/irr_driver.hpp" + +#include "config/user_config.hpp" +#include "graphics/callbacks.hpp" +#include "graphics/camera.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/lens_flare.hpp" +#include "graphics/light.hpp" +#include "graphics/lod_node.hpp" +#include "graphics/material_manager.hpp" +#include "graphics/particle_kind_manager.hpp" +#include "graphics/per_camera_node.hpp" +#include "graphics/post_processing.hpp" +#include "graphics/referee.hpp" +#include "graphics/rtts.hpp" +#include "graphics/screenquad.hpp" +#include "graphics/shaders.hpp" +#include "graphics/stkmeshscenenode.hpp" +#include "graphics/stkinstancedscenenode.hpp" +#include "graphics/wind.hpp" +#include "io/file_manager.hpp" +#include "items/item.hpp" +#include "items/item_manager.hpp" +#include "modes/world.hpp" +#include "physics/physics.hpp" +#include "tracks/track.hpp" +#include "utils/constants.hpp" +#include "utils/helpers.hpp" +#include "utils/log.hpp" +#include "utils/profiler.hpp" + +#include +#include + +#define MAX2(a, b) ((a) > (b) ? (a) : (b)) +#define MIN2(a, b) ((a) > (b) ? (b) : (a)) + +static LightShader::PointLightInfo PointLightsInfo[MAXLIGHT]; + +static void renderPointLights(unsigned count) +{ + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + + glUseProgram(LightShader::PointLightShader::Program); + glBindVertexArray(LightShader::PointLightShader::vao); + glBindBuffer(GL_ARRAY_BUFFER, LightShader::PointLightShader::vbo); + glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(LightShader::PointLightInfo), PointLightsInfo); + + setTexture(0, irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), GL_NEAREST, GL_NEAREST); + setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); + LightShader::PointLightShader + ::setUniforms(core::vector2df(float(UserConfigParams::m_width), + float(UserConfigParams::m_height)), + 200, 0, 1); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count); +} + +unsigned IrrDriver::UpdateLightsInfo(scene::ICameraSceneNode * const camnode, float dt) +{ + const u32 lightcount = m_lights.size(); + const core::vector3df &campos = camnode->getAbsolutePosition(); + + std::vector BucketedLN[15]; + for (unsigned int i = 0; i < lightcount; i++) + { + if (!m_lights[i]->isPointLight()) + { + m_lights[i]->render(); + continue; + } + const core::vector3df &lightpos = (m_lights[i]->getAbsolutePosition() - campos); + unsigned idx = (unsigned)(lightpos.getLength() / 10); + if (idx > 14) + idx = 14; + BucketedLN[idx].push_back(m_lights[i]); + } + + unsigned lightnum = 0; + + for (unsigned i = 0; i < 15; i++) + { + for (unsigned j = 0; j < BucketedLN[i].size(); j++) + { + if (++lightnum >= MAXLIGHT) + { + LightNode* light_node = BucketedLN[i].at(j); + light_node->setEnergyMultiplier(0.0f); + } + else + { + LightNode* light_node = BucketedLN[i].at(j); + + float em = light_node->getEnergyMultiplier(); + if (em < 1.0f) + { + light_node->setEnergyMultiplier(std::min(1.0f, em + dt)); + } + + const core::vector3df &pos = light_node->getAbsolutePosition(); + PointLightsInfo[lightnum].posX = pos.X; + PointLightsInfo[lightnum].posY = pos.Y; + PointLightsInfo[lightnum].posZ = pos.Z; + + PointLightsInfo[lightnum].energy = light_node->getEffectiveEnergy(); + + const core::vector3df &col = light_node->getColor(); + PointLightsInfo[lightnum].red = col.X; + PointLightsInfo[lightnum].green = col.Y; + PointLightsInfo[lightnum].blue = col.Z; + + // Light radius + PointLightsInfo[lightnum].radius = light_node->getRadius(); + } + } + if (lightnum > MAXLIGHT) + { + irr_driver->setLastLightBucketDistance(i * 10); + break; + } + } + + lightnum++; + return lightnum; +} + +void IrrDriver::renderLights(unsigned pointlightcount) +{ + //RH + if (UserConfigParams::m_gi) + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH)); + glDisable(GL_BLEND); + m_rtts->getRH().Bind(); + glUseProgram(FullScreenShader::RadianceHintsConstructionShader::Program); + glBindVertexArray(FullScreenShader::RadianceHintsConstructionShader::vao); + setTexture(0, m_rtts->getRSM().getRTT()[0], GL_LINEAR, GL_LINEAR); + setTexture(1, m_rtts->getRSM().getRTT()[1], GL_LINEAR, GL_LINEAR); + setTexture(2, m_rtts->getRSM().getDepthTexture(), GL_LINEAR, GL_LINEAR); + FullScreenShader::RadianceHintsConstructionShader::setUniforms(rsm_matrix, rh_matrix, rh_extend, 0, 1, 2); + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32); + } + + for (unsigned i = 0; i < sun_ortho_matrix.size(); i++) + sun_ortho_matrix[i] *= getInvViewMatrix(); + m_rtts->getFBO(FBO_COMBINED_TMP1_TMP2).Bind(); + if (!UserConfigParams::m_dynamic_lights) + glClearColor(.5, .5, .5, .5); + glClear(GL_COLOR_BUFFER_BIT); + if (!UserConfigParams::m_dynamic_lights) + return; + + m_rtts->getFBO(FBO_TMP1_WITH_DS).Bind(); + if (UserConfigParams::m_gi) + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI)); + m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]); + } + + if (SkyboxCubeMap) + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP)); + m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff); + } + m_rtts->getFBO(FBO_COMBINED_TMP1_TMP2).Bind(); + + if (World::getWorld() && World::getWorld()->getTrack()->hasShadows() && SkyboxCubeMap) + irr_driver->getSceneManager()->setAmbientLight(SColor(0, 0, 0, 0)); + + // Render sunlight if and only if track supports shadow + if (!World::getWorld() || World::getWorld()->getTrack()->hasShadows()) + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN)); + if (World::getWorld() && UserConfigParams::m_shadows) + m_post_processing->renderShadowedSunlight(sun_ortho_matrix, m_rtts->getShadowDepthTex()); + else + m_post_processing->renderSunlight(); + } + { + ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS)); + renderPointLights(MIN2(pointlightcount, MAXLIGHT)); + } +} + +void IrrDriver::renderSSAO() +{ + m_rtts->getFBO(FBO_SSAO).Bind(); + glClearColor(1., 1., 1., 1.); + glClear(GL_COLOR_BUFFER_BIT); + m_post_processing->renderSSAO(); + // Blur it to reduce noise. + FrameBuffer::Blit(m_rtts->getFBO(FBO_SSAO), m_rtts->getFBO(FBO_HALF1_R), GL_COLOR_BUFFER_BIT, GL_LINEAR); + m_post_processing->renderGaussian17TapBlur(irr_driver->getFBO(FBO_HALF1_R), irr_driver->getFBO(FBO_HALF2_R)); + +} \ No newline at end of file diff --git a/src/graphics/render_skybox.cpp b/src/graphics/render_skybox.cpp new file mode 100644 index 000000000..f628065c4 --- /dev/null +++ b/src/graphics/render_skybox.cpp @@ -0,0 +1,540 @@ +#include "graphics/irr_driver.hpp" + +#include "config/user_config.hpp" +#include "graphics/callbacks.hpp" +#include "graphics/camera.hpp" +#include "graphics/glwrap.hpp" +#include "graphics/lens_flare.hpp" +#include "graphics/light.hpp" +#include "graphics/lod_node.hpp" +#include "graphics/material_manager.hpp" +#include "graphics/particle_kind_manager.hpp" +#include "graphics/per_camera_node.hpp" +#include "graphics/post_processing.hpp" +#include "graphics/referee.hpp" +#include "graphics/rtts.hpp" +#include "graphics/screenquad.hpp" +#include "graphics/shaders.hpp" +#include "graphics/stkmeshscenenode.hpp" +#include "graphics/stkinstancedscenenode.hpp" +#include "graphics/wind.hpp" +#include "io/file_manager.hpp" +#include "items/item.hpp" +#include "items/item_manager.hpp" +#include "modes/world.hpp" +#include "physics/physics.hpp" +#include "tracks/track.hpp" +#include "utils/constants.hpp" +#include "utils/helpers.hpp" +#include "utils/log.hpp" +#include "utils/profiler.hpp" + +#include +#include + +#define MAX2(a, b) ((a) > (b) ? (a) : (b)) +#define MIN2(a, b) ((a) > (b) ? (b) : (a)) + +static void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z) +{ + switch (face) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + x = 1.; + y = -i; + z = -j; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + x = -1.; + y = -i; + z = j; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + x = j; + y = 1.; + z = i; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + x = j; + y = -1; + z = -i; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + x = j; + y = -i; + z = 1; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + x = -j; + y = -i; + z = -1; + break; + } + + float norm = sqrt(x * x + y * y + z * z); + x /= norm, y /= norm, z /= norm; + return; +} + +static void getYml(GLenum face, size_t width, size_t height, + float *Y00, + float *Y1minus1, float *Y10, float *Y11, + float *Y2minus2, float *Y2minus1, float *Y20, float *Y21, float *Y22) +{ + for (unsigned i = 0; i < width; i++) + { + for (unsigned j = 0; j < height; j++) + { + float x, y, z; + float fi = float(i), fj = float(j); + fi /= width, fj /= height; + fi = 2 * fi - 1, fj = 2 * fj - 1; + getXYZ(face, fi, fj, x, y, z); + + // constant part of Ylm + float c00 = 0.282095f; + float c1minus1 = 0.488603f; + float c10 = 0.488603f; + float c11 = 0.488603f; + float c2minus2 = 1.092548f; + float c2minus1 = 1.092548f; + float c21 = 1.092548f; + float c20 = 0.315392f; + float c22 = 0.546274f; + + size_t idx = i * height + j; + + Y00[idx] = c00; + Y1minus1[idx] = c1minus1 * y; + Y10[idx] = c10 * z; + Y11[idx] = c11 * x; + Y2minus2[idx] = c2minus2 * x * y; + Y2minus1[idx] = c2minus1 * y * z; + Y21[idx] = c21 * x * z; + Y20[idx] = c20 * (3 * z * z - 1); + Y22[idx] = c22 * (x * x - y * y); + } + } +} + +static float getTexelValue(unsigned i, unsigned j, size_t width, size_t height, float *Coeff, float *Y00, float *Y1minus1, float *Y10, float *Y11, + float *Y2minus2, float * Y2minus1, float * Y20, float *Y21, float *Y22) +{ + float d = sqrt((float)(i * i + j * j + 1)); + float solidangle = 1.; + size_t idx = i * height + j; + float reconstructedVal = Y00[idx] * Coeff[0]; + reconstructedVal += Y1minus1[i * height + j] * Coeff[1] + Y10[i * height + j] * Coeff[2] + Y11[i * height + j] * Coeff[3]; + reconstructedVal += Y2minus2[idx] * Coeff[4] + Y2minus1[idx] * Coeff[5] + Y20[idx] * Coeff[6] + Y21[idx] * Coeff[7] + Y22[idx] * Coeff[8]; + reconstructedVal /= solidangle; + return MAX2(255.0f * reconstructedVal, 0.f); +} + +static void unprojectSH(float *output[], size_t width, size_t height, + float *Y00[], + float *Y1minus1[], float *Y10[], float *Y11[], + float *Y2minus2[], float *Y2minus1[], float * Y20[], float *Y21[], float *Y22[], + float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff) +{ + for (unsigned face = 0; face < 6; face++) + { + for (unsigned i = 0; i < width; i++) + { + for (unsigned j = 0; j < height; j++) + { + float fi = float(i), fj = float(j); + fi /= width, fj /= height; + fi = 2 * fi - 1, fj = 2 * fj - 1; + + output[face][4 * height * i + 4 * j + 2] = getTexelValue(i, j, width, height, + redSHCoeff, + Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); + output[face][4 * height * i + 4 * j + 1] = getTexelValue(i, j, width, height, + greenSHCoeff, + Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); + output[face][4 * height * i + 4 * j] = getTexelValue(i, j, width, height, + blueSHCoeff, + Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); + } + } + } +} + +static void projectSH(float *color[], size_t width, size_t height, + float *Y00[], + float *Y1minus1[], float *Y10[], float *Y11[], + float *Y2minus2[], float *Y2minus1[], float * Y20[], float *Y21[], float *Y22[], + float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff + ) +{ + for (unsigned i = 0; i < 9; i++) + { + blueSHCoeff[i] = 0; + greenSHCoeff[i] = 0; + redSHCoeff[i] = 0; + } + float wh = float(width * height); + for (unsigned face = 0; face < 6; face++) + { + for (unsigned i = 0; i < width; i++) + { + for (unsigned j = 0; j < height; j++) + { + size_t idx = i * height + j; + float fi = float(i), fj = float(j); + fi /= width, fj /= height; + fi = 2 * fi - 1, fj = 2 * fj - 1; + + + float d = sqrt(fi * fi + fj * fj + 1); + + // Constant obtained by projecting unprojected ref values + float solidangle = 2.75f / (wh * pow(d, 1.5f)); + // pow(., 2.2) to convert from srgb + float b = pow(color[face][4 * height * i + 4 * j] / 255.f, 2.2f); + float g = pow(color[face][4 * height * i + 4 * j + 1] / 255.f, 2.2f); + float r = pow(color[face][4 * height * i + 4 * j + 2] / 255.f, 2.2f); + + assert(b >= 0.); + + blueSHCoeff[0] += b * Y00[face][idx] * solidangle; + blueSHCoeff[1] += b * Y1minus1[face][idx] * solidangle; + blueSHCoeff[2] += b * Y10[face][idx] * solidangle; + blueSHCoeff[3] += b * Y11[face][idx] * solidangle; + blueSHCoeff[4] += b * Y2minus2[face][idx] * solidangle; + blueSHCoeff[5] += b * Y2minus1[face][idx] * solidangle; + blueSHCoeff[6] += b * Y20[face][idx] * solidangle; + blueSHCoeff[7] += b * Y21[face][idx] * solidangle; + blueSHCoeff[8] += b * Y22[face][idx] * solidangle; + + greenSHCoeff[0] += g * Y00[face][idx] * solidangle; + greenSHCoeff[1] += g * Y1minus1[face][idx] * solidangle; + greenSHCoeff[2] += g * Y10[face][idx] * solidangle; + greenSHCoeff[3] += g * Y11[face][idx] * solidangle; + greenSHCoeff[4] += g * Y2minus2[face][idx] * solidangle; + greenSHCoeff[5] += g * Y2minus1[face][idx] * solidangle; + greenSHCoeff[6] += g * Y20[face][idx] * solidangle; + greenSHCoeff[7] += g * Y21[face][idx] * solidangle; + greenSHCoeff[8] += g * Y22[face][idx] * solidangle; + + + redSHCoeff[0] += r * Y00[face][idx] * solidangle; + redSHCoeff[1] += r * Y1minus1[face][idx] * solidangle; + redSHCoeff[2] += r * Y10[face][idx] * solidangle; + redSHCoeff[3] += r * Y11[face][idx] * solidangle; + redSHCoeff[4] += r * Y2minus2[face][idx] * solidangle; + redSHCoeff[5] += r * Y2minus1[face][idx] * solidangle; + redSHCoeff[6] += r * Y20[face][idx] * solidangle; + redSHCoeff[7] += r * Y21[face][idx] * solidangle; + redSHCoeff[8] += r * Y22[face][idx] * solidangle; + } + } + } +} + +static void displayCoeff(float *SHCoeff) +{ + printf("L00:%f\n", SHCoeff[0]); + printf("L1-1:%f, L10:%f, L11:%f\n", SHCoeff[1], SHCoeff[2], SHCoeff[3]); + printf("L2-2:%f, L2-1:%f, L20:%f, L21:%f, L22:%f\n", SHCoeff[4], SHCoeff[5], SHCoeff[6], SHCoeff[7], SHCoeff[8]); +} + +// Only for 9 coefficients +static void testSH(unsigned char *color[6], size_t width, size_t height, + float *blueSHCoeff, float *greenSHCoeff, float *redSHCoeff) +{ + float *Y00[6]; + float *Y1minus1[6]; + float *Y10[6]; + float *Y11[6]; + float *Y2minus2[6]; + float *Y2minus1[6]; + float *Y20[6]; + float *Y21[6]; + float *Y22[6]; + + float *testoutput[6]; + for (unsigned i = 0; i < 6; i++) + { + testoutput[i] = new float[width * height * 4]; + for (unsigned j = 0; j < width * height; j++) + { + testoutput[i][4 * j] = float(0xFF & color[i][4 * j]); + testoutput[i][4 * j + 1] = float(0xFF & color[i][4 * j + 1]); + testoutput[i][4 * j + 2] = float(0xFF & color[i][4 * j + 2]); + } + } + + for (unsigned face = 0; face < 6; face++) + { + Y00[face] = new float[width * height]; + Y1minus1[face] = new float[width * height]; + Y10[face] = new float[width * height]; + Y11[face] = new float[width * height]; + Y2minus2[face] = new float[width * height]; + Y2minus1[face] = new float[width * height]; + Y20[face] = new float[width * height]; + Y21[face] = new float[width * height]; + Y22[face] = new float[width * height]; + + getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, width, height, Y00[face], Y1minus1[face], Y10[face], Y11[face], Y2minus2[face], Y2minus1[face], Y20[face], Y21[face], Y22[face]); + } + + /* blueSHCoeff[0] = 0.54, + blueSHCoeff[1] = .6, blueSHCoeff[2] = -.27, blueSHCoeff[3] = .01, + blueSHCoeff[4] = -.12, blueSHCoeff[5] = -.47, blueSHCoeff[6] = -.15, blueSHCoeff[7] = .14, blueSHCoeff[8] = -.3; + greenSHCoeff[0] = .44, + greenSHCoeff[1] = .35, greenSHCoeff[2] = -.18, greenSHCoeff[3] = -.06, + greenSHCoeff[4] = -.05, greenSHCoeff[5] = -.22, greenSHCoeff[6] = -.09, greenSHCoeff[7] = .21, greenSHCoeff[8] = -.05; + redSHCoeff[0] = .79, + redSHCoeff[1] = .39, redSHCoeff[2] = -.34, redSHCoeff[3] = -.29, + redSHCoeff[4] = -.11, redSHCoeff[5] = -.26, redSHCoeff[6] = -.16, redSHCoeff[7] = .56, redSHCoeff[8] = .21; + + printf("Blue:\n"); + displayCoeff(blueSHCoeff); + printf("Green:\n"); + displayCoeff(greenSHCoeff); + printf("Red:\n"); + displayCoeff(redSHCoeff);*/ + + projectSH(testoutput, width, height, + Y00, + Y1minus1, Y10, Y11, + Y2minus2, Y2minus1, Y20, Y21, Y22, + blueSHCoeff, greenSHCoeff, redSHCoeff + ); + + //printf("Blue:\n"); + //displayCoeff(blueSHCoeff); + //printf("Green:\n"); + //displayCoeff(greenSHCoeff); + //printf("Red:\n"); + //displayCoeff(redSHCoeff); + + + + // Convolute in frequency space + /* float A0 = 3.141593; + float A1 = 2.094395; + float A2 = 0.785398; + blueSHCoeff[0] *= A0; + greenSHCoeff[0] *= A0; + redSHCoeff[0] *= A0; + for (unsigned i = 0; i < 3; i++) + { + blueSHCoeff[1 + i] *= A1; + greenSHCoeff[1 + i] *= A1; + redSHCoeff[1 + i] *= A1; + } + for (unsigned i = 0; i < 5; i++) + { + blueSHCoeff[4 + i] *= A2; + greenSHCoeff[4 + i] *= A2; + redSHCoeff[4 + i] *= A2; + } + + + unprojectSH(testoutput, width, height, + Y00, + Y1minus1, Y10, Y11, + Y2minus2, Y2minus1, Y20, Y21, Y22, + blueSHCoeff, greenSHCoeff, redSHCoeff + );*/ + + + /* printf("Blue:\n"); + displayCoeff(blueSHCoeff); + printf("Green:\n"); + displayCoeff(greenSHCoeff); + printf("Red:\n"); + displayCoeff(redSHCoeff); + + printf("\nAfter projection\n\n");*/ + + + + for (unsigned i = 0; i < 6; i++) + { + for (unsigned j = 0; j < width * height; j++) + { + color[i][4 * j] = char(MIN2(testoutput[i][4 * j], 255)); + color[i][4 * j + 1] = char(MIN2(testoutput[i][4 * j + 1], 255)); + color[i][4 * j + 2] = char(MIN2(testoutput[i][4 * j + 2], 255)); + } + } + + for (unsigned face = 0; face < 6; face++) + { + delete[] testoutput[face]; + delete[] Y00[face]; + delete[] Y1minus1[face]; + delete[] Y10[face]; + delete[] Y11[face]; + } +} + +/** Generate an opengl cubemap texture from 6 2d textures. +Out of legacy the sequence of textures maps to : +- 1st texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Y +- 2nd texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y +- 3rd texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_X +- 4th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_X +- 5th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +- 6th texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Z +* \param textures sequence of 6 textures. +*/ +GLuint generateCubeMapFromTextures(const std::vector &textures) +{ + assert(textures.size() == 6); + + GLuint result; + glGenTextures(1, &result); + + unsigned w = 0, h = 0; + for (unsigned i = 0; i < 6; i++) + { + w = MAX2(w, textures[i]->getOriginalSize().Width); + h = MAX2(h, textures[i]->getOriginalSize().Height); + } + + const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 }; + char *rgba[6]; + for (unsigned i = 0; i < 6; i++) + rgba[i] = new char[w * h * 4]; + for (unsigned i = 0; i < 6; i++) + { + unsigned idx = texture_permutation[i]; + + video::IImage* image = irr_driver->getVideoDriver()->createImageFromData( + textures[idx]->getColorFormat(), + textures[idx]->getSize(), + textures[idx]->lock(), + false + ); + textures[idx]->unlock(); + + image->copyToScaling(rgba[i], w, h); + image->drop(); + + glBindTexture(GL_TEXTURE_CUBE_MAP, result); + if (UserConfigParams::m_texture_compression) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); + else + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); + } + for (unsigned i = 0; i < 6; i++) + delete[] rgba[i]; + return result; +} + +void IrrDriver::generateSkyboxCubemap() +{ + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + assert(SkyboxTextures.size() == 6); + SkyboxCubeMap = generateCubeMapFromTextures(SkyboxTextures); + const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 }; + + if (SphericalHarmonicsTextures.size() == 6) + { + unsigned sh_w = 0, sh_h = 0; + for (unsigned i = 0; i < 6; i++) + { + sh_w = MAX2(sh_w, SphericalHarmonicsTextures[i]->getOriginalSize().Width); + sh_h = MAX2(sh_h, SphericalHarmonicsTextures[i]->getOriginalSize().Height); + } + + unsigned char *sh_rgba[6]; + for (unsigned i = 0; i < 6; i++) + sh_rgba[i] = new unsigned char[sh_w * sh_h * 4]; + for (unsigned i = 0; i < 6; i++) + { + unsigned idx = texture_permutation[i]; + + video::IImage* image = getVideoDriver()->createImageFromData( + SphericalHarmonicsTextures[idx]->getColorFormat(), + SphericalHarmonicsTextures[idx]->getSize(), + SphericalHarmonicsTextures[idx]->lock(), + false + ); + SphericalHarmonicsTextures[idx]->unlock(); + + image->copyToScaling(sh_rgba[i], sh_w, sh_h); + image->drop(); + } + + testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff); + + for (unsigned i = 0; i < 6; i++) + delete[] sh_rgba[i]; + } + else + { + int sh_w = 16; + int sh_h = 16; + + const video::SColorf& ambientf = irr_driver->getSceneManager()->getAmbientLight(); + video::SColor ambient = ambientf.toSColor(); + + unsigned char *sh_rgba[6]; + for (unsigned i = 0; i < 6; i++) + { + sh_rgba[i] = new unsigned char[sh_w * sh_h * 4]; + + for (int j = 0; j < sh_w * sh_h * 4; j += 4) + { + sh_rgba[i][j] = ambient.getBlue(); + sh_rgba[i][j + 1] = ambient.getGreen(); + sh_rgba[i][j + 2] = ambient.getRed(); + sh_rgba[i][j + 3] = 255; + } + } + + testSH(sh_rgba, sh_w, sh_h, blueSHCoeff, greenSHCoeff, redSHCoeff); + + for (unsigned i = 0; i < 6; i++) + delete[] sh_rgba[i]; + } + + /*for (unsigned i = 0; i < 6; i++) + { + glBindTexture(GL_TEXTURE_CUBE_MAP, ConvolutedSkyboxCubeMap); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]); + } + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0);*/ +} + +void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera) +{ + if (SkyboxTextures.empty()) + return; + if (!SkyboxCubeMap) + generateSkyboxCubemap(); + glBindVertexArray(MeshShader::SkyboxShader::cubevao); + glDisable(GL_CULL_FACE); + assert(SkyboxTextures.size() == 6); + + core::matrix4 translate; + translate.setTranslation(camera->getAbsolutePosition()); + + // Draw the sky box between the near and far clip plane + const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f; + core::matrix4 scale; + scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance)); + core::matrix4 transform = translate * scale; + core::matrix4 invtransform; + transform.getInverse(invtransform); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, SkyboxCubeMap); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glUseProgram(MeshShader::SkyboxShader::Program); + MeshShader::SkyboxShader::setUniforms(transform, + core::vector2df(float(UserConfigParams::m_width), + float(UserConfigParams::m_height)), + 0); + glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0); + glBindVertexArray(0); +} \ No newline at end of file diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 1be223a12..43f1e2c87 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -258,8 +258,8 @@ void Shaders::loadShaders() m_shaders[ES_SUNLIGHT] = glsl_noinput(dir + "pass.vert", dir + "pass.frag"); - m_shaders[ES_DISPLACE] = glsl(dir + "pass.vert", dir + "pass.frag", - m_callbacks[ES_DISPLACE]); + m_shaders[ES_DISPLACE] = glslmat(dir + "pass.vert", dir + "pass.frag", + m_callbacks[ES_DISPLACE], EMT_TRANSPARENT_ALPHA_CHANNEL); m_shaders[ES_PASSFAR] = glsl(dir + "pass.vert", dir + "pass.frag", m_callbacks[ES_COLORIZE]); @@ -325,37 +325,24 @@ void Shaders::loadShaders() FullScreenShader::MLAABlendWeightSHader::init(); FullScreenShader::MLAAGatherSHader::init(); MeshShader::ColorizeShader::init(); - MeshShader::NormalMapShader::init(); - MeshShader::ObjectPass1Shader::init(); - MeshShader::ObjectRefPass1Shader::init(); - MeshShader::InstancedObjectPass1Shader::init(); - MeshShader::InstancedObjectRefPass1Shader::init(); - MeshShader::InstancedGrassPass1Shader::init(); - MeshShader::ObjectPass2Shader::init(); - MeshShader::InstancedObjectPass2Shader::init(); - MeshShader::InstancedObjectRefPass2Shader::init(); - MeshShader::InstancedGrassPass2Shader::init(); - MeshShader::DetailledObjectPass2Shader::init(); - MeshShader::UntexturedObjectShader::init(); - MeshShader::ObjectRefPass2Shader::init(); - MeshShader::ObjectUnlitShader::init(); - MeshShader::SphereMapShader::init(); - MeshShader::SplattingShader::init(); - MeshShader::GrassPass1Shader::init(); - MeshShader::GrassPass2Shader::init(); + MeshShader::InstancedObjectPass1ShaderInstance = new MeshShader::InstancedObjectPass1Shader(); + MeshShader::InstancedObjectRefPass1ShaderInstance = new MeshShader::InstancedObjectRefPass1Shader(); + MeshShader::InstancedGrassPass1ShaderInstance = new MeshShader::InstancedGrassPass1Shader(); + MeshShader::InstancedObjectPass2ShaderInstance = new MeshShader::InstancedObjectPass2Shader(); + MeshShader::InstancedObjectRefPass2ShaderInstance = new MeshShader::InstancedObjectRefPass2Shader(); + MeshShader::InstancedGrassPass2ShaderInstance = new MeshShader::InstancedGrassPass2Shader(); MeshShader::BubbleShader::init(); - MeshShader::TransparentShader::init(); - MeshShader::TransparentFogShader::init(); MeshShader::BillboardShader::init(); LightShader::PointLightShader::init(); - MeshShader::DisplaceShader::init(); - MeshShader::DisplaceMaskShader::init(); - MeshShader::ShadowShader::init(); + MeshShader::DisplaceShaderInstance = new MeshShader::DisplaceShader(); + MeshShader::DisplaceMaskShaderInstance = new MeshShader::DisplaceMaskShader(); + MeshShader::ShadowShaderInstance = new MeshShader::ShadowShader(); MeshShader::RSMShader::init(); - MeshShader::InstancedShadowShader::init(); - MeshShader::RefShadowShader::init(); - MeshShader::InstancedRefShadowShader::init(); - MeshShader::GrassShadowShader::init(); + MeshShader::InstancedShadowShaderInstance = new MeshShader::InstancedShadowShader(); + MeshShader::RefShadowShaderInstance = new MeshShader::RefShadowShader(); + MeshShader::InstancedRefShadowShaderInstance = new MeshShader::InstancedRefShadowShader(); + MeshShader::GrassShadowShaderInstance = new MeshShader::GrassShadowShader(); + MeshShader::InstancedGrassShadowShaderInstance = new MeshShader::InstancedGrassShadowShader(); MeshShader::SkyboxShader::init(); MeshShader::ViewFrustrumShader::init(); ParticleShader::FlipParticleRender::init(); @@ -395,7 +382,7 @@ void Shaders::check(const int num) const } } -static void bypassUBO(GLint Program) +void bypassUBO(GLuint Program) { GLint VM = glGetUniformLocation(Program, "ViewMatrix"); glUniformMatrix4fv(VM, 1, GL_FALSE, irr_driver->getViewMatrix().pointer()); @@ -444,143 +431,120 @@ namespace UtilShader } } +static void +AssignTextureUnit(GLuint Program, const std::vector > assoc) +{ + glUseProgram(Program); + for (unsigned i = 0; i < assoc.size(); i++) + { + GLuint uniform = glGetUniformLocation(Program, assoc[i].second); + glUniform1i(uniform, assoc[i].first); + } + glUseProgram(0); +} + +static void +AssignUniforms(GLuint Program, std::vector &uniforms, const std::vector &name) +{ + for (unsigned i = 0; i < name.size(); i++) + { + uniforms.push_back(glGetUniformLocation(Program, name[i])); + } +} + +void glUniformMatrix4fvWraper(GLuint a, size_t b, unsigned c, const float *d) +{ + glUniformMatrix4fv(a, b, c, d); +} + +void glUniform3fWraper(GLuint a, float b, float c, float d) +{ + glUniform3f(a, b, c, d); +} + +void glUniform2fWraper(GLuint a, float b, float c) +{ + glUniform2f(a, b, c); +} + +void glUniform1fWrapper(GLuint a, float b) +{ + glUniform1f(a, b); +} + namespace MeshShader { // Solid Normal and depth pass shaders - GLuint ObjectPass1Shader::Program; - GLuint ObjectPass1Shader::uniform_MM; - GLuint ObjectPass1Shader::uniform_IMM; - GLuint ObjectPass1Shader::uniform_tex; - - void ObjectPass1Shader::init() + ObjectPass1Shader::ObjectPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, {"ModelMatrix", "InverseModelMatrix"}); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void ObjectPass1Shader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_tex) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); - } - - GLuint ObjectRefPass1Shader::Program; - GLuint ObjectRefPass1Shader::uniform_MM; - GLuint ObjectRefPass1Shader::uniform_IMM; - GLuint ObjectRefPass1Shader::uniform_TM; - GLuint ObjectRefPass1Shader::uniform_tex; - - void ObjectRefPass1Shader::init() + ObjectRefPass1Shader::ObjectRefPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "InverseModelMatrix", "TextureMatrix" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void ObjectRefPass1Shader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, const core::matrix4 &TextureMatrix, unsigned TU_tex) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); - } - - GLuint GrassPass1Shader::Program; - GLuint GrassPass1Shader::uniform_MVP; - GLuint GrassPass1Shader::uniform_TIMV; - GLuint GrassPass1Shader::uniform_tex; - GLuint GrassPass1Shader::uniform_windDir; - - void GrassPass1Shader::init() + GrassPass1Shader::GrassPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); - uniform_TIMV = glGetUniformLocation(Program, "TransposeInverseModelView"); - uniform_tex = glGetUniformLocation(Program, "tex"); - uniform_windDir = glGetUniformLocation(Program, "windDir"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "InverseModelMatrix", "windDir" }); + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void GrassPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::vector3df &windDirection, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); - glUniformMatrix4fv(uniform_TIMV, 1, GL_FALSE, TransposeInverseModelView.pointer()); - glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z); - glUniform1i(uniform_tex, TU_tex); - } - - GLuint NormalMapShader::Program; - GLuint NormalMapShader::uniform_MM; - GLuint NormalMapShader::uniform_IMM; - GLuint NormalMapShader::uniform_normalMap; - GLuint NormalMapShader::uniform_DiffuseForAlpha; - - void NormalMapShader::init() + NormalMapShader::NormalMapShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/normalmap.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/normalmap.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix"); - uniform_normalMap = glGetUniformLocation(Program, "normalMap"); - uniform_DiffuseForAlpha = glGetUniformLocation(Program, "DiffuseForAlpha"); + AssignUniforms(Program, uniforms, {"ModelMatrix", "InverseModelMatrix"}); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + TU_normalmap = 1; + TU_glossy = 0; + AssignTextureUnit(Program, { { TU_normalmap, "normalMap" }, { TU_glossy, "DiffuseForAlpha" } }); } - void NormalMapShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap, unsigned TU_uniform_DiffuseForAlpha) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer()); - glUniform1i(uniform_normalMap, TU_normalMap); - glUniform1i(uniform_DiffuseForAlpha, TU_uniform_DiffuseForAlpha); - } - - GLuint InstancedObjectPass1Shader::Program; - GLuint InstancedObjectPass1Shader::uniform_tex; - - void InstancedObjectPass1Shader::init() + InstancedObjectPass1Shader::InstancedObjectPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str()); - uniform_tex = glGetUniformLocation(Program, "tex"); + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -588,24 +552,17 @@ namespace MeshShader } } - void InstancedObjectPass1Shader::setUniforms(unsigned TU_tex) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniform1i(uniform_tex, TU_tex); - } + InstancedObjectPass1Shader *InstancedObjectPass1ShaderInstance; - GLuint InstancedObjectRefPass1Shader::Program; - GLuint InstancedObjectRefPass1Shader::uniform_tex; - - void InstancedObjectRefPass1Shader::init() + InstancedObjectRefPass1Shader::InstancedObjectRefPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str()); - uniform_tex = glGetUniformLocation(Program, "tex"); + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -613,26 +570,18 @@ namespace MeshShader } } - void InstancedObjectRefPass1Shader::setUniforms(unsigned TU_tex) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniform1i(uniform_tex, TU_tex); - } + InstancedObjectRefPass1Shader *InstancedObjectRefPass1ShaderInstance; - GLuint InstancedGrassPass1Shader::Program; - GLuint InstancedGrassPass1Shader::uniform_windDir; - GLuint InstancedGrassPass1Shader::uniform_tex; - - void InstancedGrassPass1Shader::init() + InstancedGrassPass1Shader::InstancedGrassPass1Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str()); - uniform_windDir = glGetUniformLocation(Program, "windDir"); - uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, { "windDir" }); + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -640,35 +589,16 @@ namespace MeshShader } } - void InstancedGrassPass1Shader::setUniforms(const core::vector3df &windDir, unsigned TU_tex) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniform3f(uniform_windDir, windDir.X, windDir.Y, windDir.Z); - glUniform1i(uniform_tex, TU_tex); - } + InstancedGrassPass1Shader *InstancedGrassPass1ShaderInstance; // Solid Lit pass shaders - - GLuint ObjectPass2Shader::Program; - GLuint ObjectPass2Shader::uniform_MM; - GLuint ObjectPass2Shader::uniform_TM; - GLuint ObjectPass2Shader::uniform_ambient; - GLuint ObjectPass2Shader::TU_Albedo; - - void ObjectPass2Shader::init() + ObjectPass2Shader::ObjectPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "TextureMatrix", "ambient" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -676,52 +606,22 @@ namespace MeshShader } TU_Albedo = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" } }); } - void ObjectPass2Shader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + ObjectPass2Shader *ObjectPass2ShaderInstance; - GLuint InstancedObjectPass2Shader::Program; - GLuint InstancedObjectPass2Shader::uniform_VP; - GLuint InstancedObjectPass2Shader::uniform_TM; - GLuint InstancedObjectPass2Shader::uniform_ambient; - GLuint InstancedObjectPass2Shader::TU_Albedo; - - void InstancedObjectPass2Shader::init() + InstancedObjectPass2Shader::InstancedObjectPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str()); - uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, { "ambient" }); TU_Albedo = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" } }); if (!UserConfigParams::m_ubo_disabled) { @@ -730,112 +630,49 @@ namespace MeshShader } } - void InstancedObjectPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + InstancedObjectPass2Shader *InstancedObjectPass2ShaderInstance; - GLuint InstancedObjectRefPass2Shader::Program; - GLuint InstancedObjectRefPass2Shader::uniform_VP; - GLuint InstancedObjectRefPass2Shader::uniform_TM; - GLuint InstancedObjectRefPass2Shader::uniform_ambient; - GLuint InstancedObjectRefPass2Shader::TU_Albedo; - - void InstancedObjectRefPass2Shader::init() + InstancedObjectRefPass2Shader::InstancedObjectRefPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str()); - uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, { "ambient" }); TU_Albedo = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" } }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void InstancedObjectRefPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + InstancedObjectRefPass2Shader *InstancedObjectRefPass2ShaderInstance; - GLuint DetailledObjectPass2Shader::Program; - GLuint DetailledObjectPass2Shader::uniform_MM; - GLuint DetailledObjectPass2Shader::uniform_ambient; - GLuint DetailledObjectPass2Shader::TU_Albedo; - GLuint DetailledObjectPass2Shader::TU_detail; - - void DetailledObjectPass2Shader::init() + DetailledObjectPass2Shader::DetailledObjectPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/detailledobject_pass2.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_Detail = glGetUniformLocation(Program, "Detail"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "ambient" }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); TU_Albedo = 3; TU_detail = 4; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUniform1i(uniform_Detail, TU_detail); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" }, { TU_detail, "Detail" } }); } - void DetailledObjectPass2Shader::setUniforms(const core::matrix4 &ModelMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + DetailledObjectPass2Shader *DetailledObjectPass2ShaderInstance; - GLuint ObjectUnlitShader::Program; - GLuint ObjectUnlitShader::uniform_MM; - GLuint ObjectUnlitShader::TU_tex; - - void ObjectUnlitShader::init() + ObjectUnlitShader::ObjectUnlitShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - GLuint uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, { "ModelMatrix" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -843,76 +680,18 @@ namespace MeshShader } TU_tex = 3; - glUseProgram(Program); - glUniform1i(uniform_tex, TU_tex); - glUseProgram(0); + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void ObjectUnlitShader::setUniforms(const core::matrix4 &ModelMatrix) + ObjectUnlitShader *ObjectUnlitShaderInstance; + + ObjectRefPass2Shader::ObjectRefPass2Shader() { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - } - - GLuint UntexturedObjectShader::Program; - GLuint UntexturedObjectShader::uniform_MM; - GLuint UntexturedObjectShader::uniform_ambient; - - void UntexturedObjectShader::init() - { - Program = LoadProgram( - GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), - GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), - GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/untextured_object.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); - if (!UserConfigParams::m_ubo_disabled) - { - GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); - glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); - } - - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUseProgram(0); - } - - void UntexturedObjectShader::setUniforms(const core::matrix4 &ModelMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } - - - GLuint ObjectRefPass2Shader::Program; - GLuint ObjectRefPass2Shader::uniform_MM; - GLuint ObjectRefPass2Shader::uniform_TM; - GLuint ObjectRefPass2Shader::uniform_ambient; - GLuint ObjectRefPass2Shader::TU_Albedo; - - void ObjectRefPass2Shader::init() - { - initGL(); Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "TextureMatrix", "ambient" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -920,139 +699,52 @@ namespace MeshShader } TU_Albedo = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" } }); } - void ObjectRefPass2Shader::setUniforms(const core::matrix4 &ModelMatrix, - const core::matrix4 &TextureMatrix) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + ObjectRefPass2Shader *ObjectRefPass2ShaderInstance; - GLuint GrassPass2Shader::Program; - GLuint GrassPass2Shader::uniform_MVP; - GLuint GrassPass2Shader::uniform_ambient; - GLuint GrassPass2Shader::uniform_windDir; - GLuint GrassPass2Shader::TU_Albedo; - - void GrassPass2Shader::init() + GrassPass2Shader::GrassPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/grass_pass2.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); - uniform_windDir = glGetUniformLocation(Program, "windDir"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "windDir", "ambient" }); TU_Albedo = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" } }); } - void GrassPass2Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, - const core::vector3df &windDirection) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z); - } + GrassPass2Shader *GrassPass2ShaderInstance; - GLuint InstancedGrassPass2Shader::Program; - GLuint InstancedGrassPass2Shader::uniform_VP; - GLuint InstancedGrassPass2Shader::uniform_ambient; - GLuint InstancedGrassPass2Shader::uniform_windDir; - GLuint InstancedGrassPass2Shader::uniform_invproj; - GLuint InstancedGrassPass2Shader::uniform_IVM; - GLuint InstancedGrassPass2Shader::uniform_SunDir; - GLuint InstancedGrassPass2Shader::TU_Albedo; - GLuint InstancedGrassPass2Shader::TU_dtex; - - void InstancedGrassPass2Shader::init() + InstancedGrassPass2Shader::InstancedGrassPass2Shader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/grass_pass2.frag").c_str()); - uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix"); - GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - GLuint uniform_dtex = glGetUniformLocation(Program, "dtex"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); - uniform_windDir = glGetUniformLocation(Program, "windDir"); - uniform_invproj = glGetUniformLocation(Program, "invproj"); - uniform_IVM = glGetUniformLocation(Program, "InverseViewMatrix"); - uniform_SunDir = glGetUniformLocation(Program, "SunDir"); + AssignUniforms(Program, uniforms, { "windDir", "SunDir", "ambient" }); TU_Albedo = 3; TU_dtex = 4; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_Albedo, TU_Albedo); - glUniform1i(uniform_dtex, TU_dtex); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_Albedo, "Albedo" }, { TU_dtex, "dtex" } }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void InstancedGrassPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &InverseViewMatrix, const core::matrix4 &invproj, const core::vector3df &windDirection, const core::vector3df &SunDir) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer()); - glUniformMatrix4fv(uniform_invproj, 1, GL_FALSE, invproj.pointer()); - glUniformMatrix4fv(uniform_IVM, 1, GL_FALSE, InverseViewMatrix.pointer()); - glUniform3f(uniform_SunDir, SunDir.X, SunDir.Y, SunDir.Z); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z); - } + InstancedGrassPass2Shader *InstancedGrassPass2ShaderInstance; - GLuint SphereMapShader::Program; - GLuint SphereMapShader::uniform_MM; - GLuint SphereMapShader::uniform_IMM; - GLuint SphereMapShader::uniform_ambient; - GLuint SphereMapShader::TU_tex; - - void SphereMapShader::init() + SphereMapShader::SphereMapShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_spheremap.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); - GLuint uniform_tex = glGetUniformLocation(Program, "tex"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "InverseModelMatrix", "ambient" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -1060,71 +752,28 @@ namespace MeshShader } TU_tex = 3; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_tex, TU_tex); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_tex, "tex" } }); } - void SphereMapShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, const SColorf &ambient) - { - if (UserConfigParams::m_ubo_disabled) - bypassUBO(Program); - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer()); - glUniform3f(uniform_ambient, ambient.r, ambient.g, ambient.b); - } + SphereMapShader *SphereMapShaderInstance; - GLuint SplattingShader::Program; - GLuint SplattingShader::uniform_MM; - GLuint SplattingShader::uniform_ambient; - GLuint SplattingShader::TU_tex_layout; - GLuint SplattingShader::TU_tex_detail0; - GLuint SplattingShader::TU_tex_detail1; - GLuint SplattingShader::TU_tex_detail2; - GLuint SplattingShader::TU_tex_detail3; - - void SplattingShader::init() + SplattingShader::SplattingShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/splatting.frag").c_str()); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - GLuint uniform_tex_layout = glGetUniformLocation(Program, "tex_layout"); - GLuint uniform_tex_detail0 = glGetUniformLocation(Program, "tex_detail0"); - GLuint uniform_tex_detail1 = glGetUniformLocation(Program, "tex_detail1"); - GLuint uniform_tex_detail2 = glGetUniformLocation(Program, "tex_detail2"); - GLuint uniform_tex_detail3 = glGetUniformLocation(Program, "tex_detail3"); - GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap"); - GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap"); - GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO"); - uniform_ambient = glGetUniformLocation(Program, "ambient"); + AssignUniforms(Program, uniforms, {"ModelMatrix", "ambient"}); TU_tex_layout = 3; TU_tex_detail0 = 4; TU_tex_detail1 = 5; TU_tex_detail2 = 6; TU_tex_detail3 = 7; - glUseProgram(Program); - glUniform1i(uniform_DiffuseMap, 0); - glUniform1i(uniform_SpecularMap, 1); - glUniform1i(uniform_SSAO, 2); - glUniform1i(uniform_tex_layout, TU_tex_layout); - glUniform1i(uniform_tex_detail0, TU_tex_detail0); - glUniform1i(uniform_tex_detail1, TU_tex_detail1); - glUniform1i(uniform_tex_detail2, TU_tex_detail2); - glUniform1i(uniform_tex_detail3, TU_tex_detail3); - glUseProgram(0); + AssignTextureUnit(Program, { { 0, "DiffuseMap" }, { 1, "SpecularMap" }, { 2, "SSAO" }, { TU_tex_layout, "tex_layout" }, + { TU_tex_detail0, "tex_detail0" }, { TU_tex_detail1, "tex_detail1" }, { TU_tex_detail2, "tex_detail2" }, { TU_tex_detail3, "tex_detail3" } }); } - void SplattingShader::setUniforms(const core::matrix4 &ModelMatrix) - { - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight(); - glUniform3f(uniform_ambient, s.r, s.g, s.b); - } + SplattingShader *SplattingShaderInstance; GLuint BubbleShader::Program; GLuint BubbleShader::uniform_MVP; @@ -1150,77 +799,41 @@ namespace MeshShader glUniform1f(uniform_transparency, transparency); } - GLuint TransparentShader::Program; - GLuint TransparentShader::uniform_MVP; - GLuint TransparentShader::uniform_TM; - GLuint TransparentShader::uniform_tex; - - void TransparentShader::init() + TransparentShader::TransparentShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, {"ModelMatrix", "TextureMatrix" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + TU_tex = 0; + + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void TransparentShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); - } + TransparentShader *TransparentShaderInstance; - GLuint TransparentFogShader::Program; - GLuint TransparentFogShader::uniform_MVP; - GLuint TransparentFogShader::uniform_TM; - GLuint TransparentFogShader::uniform_tex; - GLuint TransparentFogShader::uniform_fogmax; - GLuint TransparentFogShader::uniform_startH; - GLuint TransparentFogShader::uniform_endH; - GLuint TransparentFogShader::uniform_start; - GLuint TransparentFogShader::uniform_end; - GLuint TransparentFogShader::uniform_col; - - void TransparentFogShader::init() + TransparentFogShader::TransparentFogShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparentfog.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelMatrix"); - uniform_TM = glGetUniformLocation(Program, "TextureMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); - uniform_fogmax = glGetUniformLocation(Program, "fogmax"); - uniform_startH = glGetUniformLocation(Program, "startH"); - uniform_endH = glGetUniformLocation(Program, "endH"); - uniform_start = glGetUniformLocation(Program, "start"); - uniform_end = glGetUniformLocation(Program, "end"); - uniform_col = glGetUniformLocation(Program, "col"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "TextureMatrix", "fogmax", "startH", "endH", "start", "end", "col" }); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } + TU_tex = 0; + + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void TransparentFogShader::setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix, float fogmax, float startH, float endH, float start, float end, const core::vector3df &col, const core::vector3df &campos, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer()); - glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer()); - glUniform1f(uniform_fogmax, fogmax); - glUniform1f(uniform_startH, startH); - glUniform1f(uniform_endH, endH); - glUniform1f(uniform_start, start); - glUniform1f(uniform_end, end); - glUniform3f(uniform_col, col.X, col.Y, col.Z); - glUniform1i(uniform_tex, TU_tex); - } + TransparentFogShader *TransparentFogShaderInstance; GLuint BillboardShader::Program; GLuint BillboardShader::attrib_corner; @@ -1284,10 +897,7 @@ namespace MeshShader glUniform3f(uniform_col, r, g, b); } - GLuint ShadowShader::Program; - GLuint ShadowShader::uniform_MM; - - void ShadowShader::init() + ShadowShader::ShadowShader() { // Geometry shader needed if (irr_driver->getGLSLVersion() < 150) @@ -1305,21 +915,17 @@ namespace MeshShader GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str()); } - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); + AssignUniforms(Program, uniforms, { "ModelMatrix" }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void ShadowShader::setUniforms(const core::matrix4 &ModelMatrix) - { - - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - } + ShadowShader *ShadowShaderInstance; GLuint RSMShader::Program; GLuint RSMShader::uniform_MM; - GLuint RSMShader::uniform_tex; GLuint RSMShader::uniform_RSMMatrix; + GLuint RSMShader::TU_tex; void RSMShader::init() { @@ -1329,20 +935,17 @@ namespace MeshShader GL_VERTEX_SHADER, file_manager->getAsset("shaders/rsm.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/rsm.frag").c_str()); uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); uniform_RSMMatrix = glGetUniformLocation(Program, "RSMMatrix"); + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void RSMShader::setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex) + void RSMShader::setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix) { glUniformMatrix4fv(uniform_RSMMatrix, 1, GL_FALSE, RSMMatrix.pointer()); glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); } - GLuint InstancedShadowShader::Program; - - void InstancedShadowShader::init() + InstancedShadowShader::InstancedShadowShader() { // Geometry shader needed if (irr_driver->getGLSLVersion() < 150) @@ -1366,15 +969,9 @@ namespace MeshShader glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void InstancedShadowShader::setUniforms() - { - } + InstancedShadowShader *InstancedShadowShaderInstance; - GLuint RefShadowShader::Program; - GLuint RefShadowShader::uniform_MM; - GLuint RefShadowShader::uniform_tex; - - void RefShadowShader::init() + RefShadowShader::RefShadowShader() { // Geometry shader needed if (irr_driver->getGLSLVersion() < 150) @@ -1392,22 +989,17 @@ namespace MeshShader GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); } - uniform_tex = glGetUniformLocation(Program, "tex"); - uniform_MM = glGetUniformLocation(Program, "ModelMatrix"); + AssignUniforms(Program, uniforms, { "ModelMatrix" }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + TU_tex = 0; + + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - void RefShadowShader::setUniforms(const core::matrix4 &ModelMatrix, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); - } + RefShadowShader *RefShadowShaderInstance; - GLuint InstancedRefShadowShader::Program; - GLuint InstancedRefShadowShader::uniform_tex; - - void InstancedRefShadowShader::init() + InstancedRefShadowShader::InstancedRefShadowShader() { // Geometry shader needed if (irr_driver->getGLSLVersion() < 150) @@ -1427,50 +1019,78 @@ namespace MeshShader GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); } - uniform_tex = glGetUniformLocation(Program, "tex"); + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void InstancedRefShadowShader::setUniforms(unsigned TU_tex) + InstancedRefShadowShader *InstancedRefShadowShaderInstance; + + GrassShadowShader::GrassShadowShader() { - glUniform1i(uniform_tex, TU_tex); + // Geometry shader needed + if (irr_driver->getGLSLVersion() < 150) + return; + if (irr_driver->hasVSLayerExtension()) + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow_grass.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); + } + else + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/shadow_grass.vert").c_str(), + GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); + } + AssignUniforms(Program, uniforms, { "ModelMatrix", "windDir" }); + GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); + glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); + TU_tex = 0; + + AssignTextureUnit(Program, { { TU_tex, "tex" } }); } - GLuint GrassShadowShader::Program; - GLuint GrassShadowShader::uniform_MVP; - GLuint GrassShadowShader::uniform_tex; - GLuint GrassShadowShader::uniform_windDir; + GrassShadowShader *GrassShadowShaderInstance; - void GrassShadowShader::init() + InstancedGrassShadowShader::InstancedGrassShadowShader() { - return; - Program = LoadProgram( - GL_VERTEX_SHADER, file_manager->getAsset("shaders/grass_pass.vert").c_str(), - GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelViewProjectionMatrix"); - uniform_tex = glGetUniformLocation(Program, "tex"); - uniform_windDir = glGetUniformLocation(Program, "windDir"); + // Geometry shader needed + if (irr_driver->getGLSLVersion() < 150) + return; + if (irr_driver->hasVSLayerExtension()) + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); + } + else + { + Program = LoadProgram( + GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(), + GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanciedgrassshadow.vert").c_str(), + GL_GEOMETRY_SHADER, file_manager->getAsset("shaders/shadow.geom").c_str(), + GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_unlit.frag").c_str()); + } + TU_tex = 0; + AssignTextureUnit(Program, { { TU_tex, "tex" } }); + + AssignUniforms(Program, uniforms, { "windDir" }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void GrassShadowShader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer()); - glUniform1i(uniform_tex, TU_tex); - glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z); - } + InstancedGrassShadowShader *InstancedGrassShadowShaderInstance; - GLuint DisplaceMaskShader::Program; - GLuint DisplaceMaskShader::uniform_MVP; - - void DisplaceMaskShader::init() + DisplaceMaskShader::DisplaceMaskShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/white.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelMatrix"); + AssignUniforms(Program, uniforms, { "ModelMatrix"}); if (!UserConfigParams::m_ubo_disabled) { GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); @@ -1478,46 +1098,25 @@ namespace MeshShader } } - void DisplaceMaskShader::setUniforms(const core::matrix4 &ModelMatrix) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer()); - } + DisplaceMaskShader *DisplaceMaskShaderInstance; - GLuint DisplaceShader::Program; - GLuint DisplaceShader::uniform_MVP; - GLuint DisplaceShader::uniform_displacement_tex; - GLuint DisplaceShader::uniform_mask_tex; - GLuint DisplaceShader::uniform_color_tex; - GLuint DisplaceShader::uniform_tex; - GLuint DisplaceShader::uniform_dir; - GLuint DisplaceShader::uniform_dir2; - void DisplaceShader::init() + DisplaceShader::DisplaceShader() { Program = LoadProgram( GL_VERTEX_SHADER, file_manager->getAsset("shaders/displace.vert").c_str(), GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/displace.frag").c_str()); - uniform_MVP = glGetUniformLocation(Program, "ModelMatrix"); - uniform_displacement_tex = glGetUniformLocation(Program, "displacement_tex"); - uniform_color_tex = glGetUniformLocation(Program, "color_tex"); - uniform_mask_tex = glGetUniformLocation(Program, "mask_tex"); - uniform_dir = glGetUniformLocation(Program, "dir"); - uniform_dir2 = glGetUniformLocation(Program, "dir2"); - uniform_tex = glGetUniformLocation(Program, "tex"); + AssignUniforms(Program, uniforms, { "ModelMatrix", "dir", "dir2" }); + TU_displacement_tex = 0; + TU_color_tex = 1; + TU_mask_tex = 2; + TU_tex = 3; + AssignTextureUnit(Program, { { TU_displacement_tex, "displacement_tex" }, { TU_color_tex, "color_tex" }, { TU_mask_tex, "mask_tex" }, { TU_tex, "tex" } }); GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData"); glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0); } - void DisplaceShader::setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex) - { - glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer()); - glUniform2f(uniform_dir, dir.X, dir.Y); - glUniform2f(uniform_dir2, dir2.X, dir2.Y); - glUniform1i(uniform_displacement_tex, TU_displacement_tex); - glUniform1i(uniform_mask_tex, TU_mask_tex); - glUniform1i(uniform_color_tex, TU_color_tex); - glUniform1i(uniform_tex, TU_tex); - } + DisplaceShader *DisplaceShaderInstance; GLuint SkyboxShader::Program; GLuint SkyboxShader::attrib_position; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 885d8807a..e5d0eecd2 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -20,6 +20,8 @@ #include #include #include +#include "config/user_config.hpp" +#include "utils/singleton.hpp" typedef unsigned int GLuint; using namespace irr; @@ -47,196 +49,239 @@ public: }; } +void glUniformMatrix4fvWraper(GLuint, size_t, unsigned, const float *mat); +void glUniform3fWraper(GLuint, float, float, float); +void glUniform2fWraper(GLuint a, float b, float c); +void glUniform1fWrapper(GLuint, float); + +struct UniformHelper +{ + template + static void setUniformsHelper(const std::vector &uniforms) + { + } + + template + static void setUniformsHelper(const std::vector &uniforms, const core::matrix4 &mat, Args... arg) + { +#ifndef GL_FALSE +#define GL_FALSE 0 +#endif + glUniformMatrix4fvWraper(uniforms[N], 1, GL_FALSE, mat.pointer()); + setUniformsHelper(uniforms, arg...); + } + + template + static void setUniformsHelper(const std::vector &uniforms, const video::SColorf &col, Args... arg) + { + glUniform3fWraper(uniforms[N], col.r, col.g, col.b); + setUniformsHelper(uniforms, arg...); + } + + template + static void setUniformsHelper(const std::vector &uniforms, const core::vector3df &v, Args... arg) + { + glUniform3fWraper(uniforms[N], v.X, v.Y, v.Z); + setUniformsHelper(uniforms, arg...); + } + + + template + static void setUniformsHelper(const std::vector &uniforms, const core::vector2df &v, Args... arg) + { + glUniform2fWraper(uniforms[N], v.X, v.Y); + setUniformsHelper(uniforms, arg...); + } + + template + static void setUniformsHelper(const std::vector &uniforms, float f, Args... arg) + { + glUniform1fWrapper(uniforms[N], f); + setUniformsHelper(uniforms, arg...); + } + +}; + +void bypassUBO(GLuint Program); + +template +class ShaderHelper +{ +protected: + std::vector uniforms; +public: + GLuint Program; + + void setUniforms(const Args & ... args) const + { + if (UserConfigParams::m_ubo_disabled) + bypassUBO(Program); + UniformHelper::setUniformsHelper(uniforms, args...); + } +}; + +template +class ShaderHelperSingleton : public Singleton +{ +protected: + std::vector uniforms; +public: + friend class Singleton; + GLuint Program; + + void setUniforms(const Args & ... args) const + { + if (UserConfigParams::m_ubo_disabled) + bypassUBO(Program); + UniformHelper::setUniformsHelper(uniforms, args...); + } +}; + namespace MeshShader { -class ObjectPass1Shader +class ObjectPass1Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_IMM, uniform_tex; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_tex); + GLuint TU_tex; + ObjectPass1Shader(); }; -class ObjectRefPass1Shader +class ObjectRefPass1Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_TM, uniform_IMM, uniform_tex; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, const core::matrix4 &TextureMatrix, unsigned TU_texture); + GLuint TU_tex; + ObjectRefPass1Shader(); }; -class GrassPass1Shader +class GrassPass1Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_TIMV, uniform_tex, uniform_windDir; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::vector3df &windDirection, unsigned TU_tex); + GrassPass1Shader(); }; -class NormalMapShader +class NormalMapShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_IMM, uniform_normalMap, uniform_DiffuseForAlpha; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, unsigned TU_normalMap, unsigned TU_uniform_DiffuseForAlpha); + GLuint TU_normalmap, TU_glossy; + NormalMapShader(); }; -class InstancedObjectPass1Shader +class InstancedObjectPass1Shader : public ShaderHelper<> { public: - static GLuint Program; - static GLuint uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(unsigned TU_tex); + InstancedObjectPass1Shader(); }; -class InstancedObjectRefPass1Shader +extern InstancedObjectPass1Shader *InstancedObjectPass1ShaderInstance; + +class InstancedObjectRefPass1Shader : public ShaderHelper<> { public: - static GLuint Program; - static GLuint uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(unsigned TU_tex); + InstancedObjectRefPass1Shader(); }; -class InstancedGrassPass1Shader +extern InstancedObjectRefPass1Shader *InstancedObjectRefPass1ShaderInstance; + +class InstancedGrassPass1Shader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_windDir, uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::vector3df &windDir, unsigned TU_tex); + InstancedGrassPass1Shader(); }; -class ObjectPass2Shader +extern InstancedGrassPass1Shader *InstancedGrassPass1ShaderInstance; + +class ObjectPass2Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_TM, uniform_ambient; - static GLuint TU_Albedo; + GLuint TU_Albedo; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix); + ObjectPass2Shader(); }; -class InstancedObjectPass2Shader +class InstancedObjectPass2Shader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_VP, uniform_TM, uniform_ambient; - static GLuint TU_Albedo; + GLuint TU_Albedo; - static void init(); - static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix); + InstancedObjectPass2Shader(); }; -class InstancedObjectRefPass2Shader +extern InstancedObjectPass2Shader *InstancedObjectPass2ShaderInstance; + +class InstancedObjectRefPass2Shader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_VP, uniform_TM, uniform_ambient; - static GLuint TU_Albedo; + GLuint TU_Albedo; - static void init(); - static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix); + InstancedObjectRefPass2Shader(); }; -class DetailledObjectPass2Shader +extern InstancedObjectRefPass2Shader *InstancedObjectRefPass2ShaderInstance; + +class DetailledObjectPass2Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_ambient; - static GLuint TU_Albedo, TU_detail; + GLuint TU_Albedo, TU_detail; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + DetailledObjectPass2Shader(); }; -class UntexturedObjectShader +class ObjectUnlitShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_ambient; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + ObjectUnlitShader(); }; -class ObjectUnlitShader +class ObjectRefPass2Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM; - static GLuint TU_tex; + GLuint TU_Albedo; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + ObjectRefPass2Shader(); }; -class ObjectRefPass2Shader +class GrassPass2Shader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_TM, uniform_ambient; - static GLuint TU_Albedo; + GLuint TU_Albedo; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix); + GrassPass2Shader(); }; -class GrassPass2Shader +class InstancedGrassPass2Shader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_ambient, uniform_windDir; - static GLuint TU_Albedo; + GLuint TU_Albedo, TU_dtex; - static void init(); - static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection); + InstancedGrassPass2Shader(); }; -class InstancedGrassPass2Shader +extern InstancedGrassPass2Shader *InstancedGrassPass2ShaderInstance; + +class SphereMapShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_VP, uniform_TM, uniform_IVM, uniform_ambient, uniform_windDir, uniform_invproj, uniform_SunDir; - static GLuint TU_Albedo, TU_dtex; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &InverseViewMatrix, const core::matrix4 &invproj, const core::vector3df &windDirection, const core::vector3df &SunDir); + SphereMapShader(); }; -class SphereMapShader +class SplattingShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MM, uniform_IMM, uniform_ambient; - static GLuint TU_tex; + GLuint TU_tex_layout, TU_tex_detail0, TU_tex_detail1, TU_tex_detail2, TU_tex_detail3; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, const video::SColorf &ambient); -}; - -class SplattingShader -{ -public: - static GLuint Program; - static GLuint uniform_MM, uniform_ambient; - static GLuint TU_tex_layout, TU_tex_detail0, TU_tex_detail1, TU_tex_detail2, TU_tex_detail3; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + SplattingShader(); }; class BubbleShader @@ -249,24 +294,20 @@ public: static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, unsigned TU_tex, float time, float transparency); }; -class TransparentShader +class TransparentShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_TM, uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix, unsigned TU_tex); + TransparentShader(); }; -class TransparentFogShader +class TransparentFogShader : public ShaderHelperSingleton { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_TM, uniform_tex, uniform_fogmax, uniform_startH, uniform_endH, uniform_start, uniform_end, uniform_col; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &TextureMatrix, float fogmax, float startH, float endH, float start, float end, const core::vector3df &col, const core::vector3df &campos, unsigned TU_tex); + TransparentFogShader(); }; class BillboardShader @@ -291,85 +332,89 @@ public: static void setUniforms(const core::matrix4 &ModelMatrix, float r, float g, float b); }; -class ShadowShader +class ShadowShader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MM, uniform_ViewProjectionMatrixesUBO; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + ShadowShader(); }; +extern ShadowShader *ShadowShaderInstance; + class RSMShader { public: static GLuint Program; - static GLuint uniform_MM, uniform_tex, uniform_RSMMatrix; + static GLuint uniform_MM, uniform_RSMMatrix; + static GLuint TU_tex; static void init(); - static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix, unsigned TU_tex); + static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &ModelMatrix); }; -class InstancedShadowShader +class InstancedShadowShader : public ShaderHelper<> { public: - static GLuint Program; - - static void init(); - static void setUniforms(); + InstancedShadowShader(); }; -class RefShadowShader +extern InstancedShadowShader *InstancedShadowShaderInstance; + +class RefShadowShader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MM, uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, unsigned TU_tex); + RefShadowShader(); }; -class InstancedRefShadowShader +extern RefShadowShader *RefShadowShaderInstance; + +class InstancedRefShadowShader : public ShaderHelper<> { public: - static GLuint Program; - static GLuint uniform_tex; + GLuint TU_tex; - static void init(); - static void setUniforms(unsigned TU_tex); + InstancedRefShadowShader(); }; -class GrassShadowShader +extern InstancedRefShadowShader *InstancedRefShadowShaderInstance; + +class GrassShadowShader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_tex, uniform_windDir; - - static void init(); - static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection, unsigned TU_tex); + GLuint TU_tex; + GrassShadowShader(); }; -class DisplaceMaskShader +extern GrassShadowShader *GrassShadowShaderInstance; + +class InstancedGrassShadowShader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MVP; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix); + GLuint TU_tex; + InstancedGrassShadowShader(); }; -class DisplaceShader +extern InstancedGrassShadowShader *InstancedGrassShadowShaderInstance; + +class DisplaceMaskShader : public ShaderHelper { public: - static GLuint Program; - static GLuint uniform_MVP, uniform_displacement_tex, uniform_mask_tex, uniform_color_tex, uniform_tex, uniform_dir, uniform_dir2; - - static void init(); - static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex); + DisplaceMaskShader(); }; +extern DisplaceMaskShader *DisplaceMaskShaderInstance; + +class DisplaceShader : public ShaderHelper +{ +public: + GLuint TU_displacement_tex, TU_mask_tex, TU_color_tex, TU_tex; + + DisplaceShader(); +}; + +extern DisplaceShader *DisplaceShaderInstance; + class SkyboxShader { public: diff --git a/src/graphics/stkanimatedmesh.cpp b/src/graphics/stkanimatedmesh.cpp index 727144398..babbfdad9 100644 --- a/src/graphics/stkanimatedmesh.cpp +++ b/src/graphics/stkanimatedmesh.cpp @@ -6,6 +6,7 @@ #include "config/user_config.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" +#include "graphics/camera.hpp" #include "utils/profiler.hpp" using namespace irr; @@ -38,10 +39,8 @@ void STKAnimatedMesh::setMesh(scene::IAnimatedMesh* mesh) { firstTime = true; GLmeshes.clear(); - for (unsigned i = 0; i < FPSM_COUNT; i++) - GeometricMesh[i].clearWithoutDeleting(); - for (unsigned i = 0; i < SM_COUNT; i++) - ShadedMesh[i].clearWithoutDeleting(); + for (unsigned i = 0; i < MAT_COUNT; i++) + MeshSolidMaterial[i].clearWithoutDeleting(); CAnimatedMeshSceneNode::setMesh(mesh); } @@ -97,10 +96,8 @@ void STKAnimatedMesh::render() } else { - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); - GeometricMesh[GeometricType].push_back(&mesh); - ShadedMesh[ShadedType].push_back(&mesh); + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); + MeshSolidMaterial[MatType].push_back(&mesh); } std::pair p = getVAOOffsetAndBase(mb); mesh.vaoBaseVertex = p.first; @@ -116,13 +113,13 @@ void STKAnimatedMesh::render() const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; if (isObject(material.MaterialType)) { - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) - { - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, getVBO(mb->getVertexType())); - glBufferSubData(GL_ARRAY_BUFFER, GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices()); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == TRANSPARENT_PASS || irr_driver->getPhase() == SHADOW_PASS) + { + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, getVBO(mb->getVertexType())); + glBufferSubData(GL_ARRAY_BUFFER, GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices()); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } } if (mb) GLmeshes[i].TextureMatrix = getMaterial(i).getTextureMatrix(0); @@ -136,78 +133,24 @@ void STKAnimatedMesh::render() continue; } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); - TransposeInverseModelView = computeTIMV(AbsoluteTransformation); core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); GLMesh* mesh; - for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterial[MAT_DEFAULT]) + ListMatDefault::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterial[MAT_ALPHA_REF]) + ListMatAlphaRef::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterial[MAT_DETAIL]) + ListMatDetails::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - return; - } - - if (irr_driver->getPhase() == SOLID_LIT_PASS) - { - core::matrix4 invmodel; - AbsoluteTransformation.getInverse(invmodel); - - GLMesh* mesh; - for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in (mesh, ShadedMesh[SM_UNLIT]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_DETAILS]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterial[MAT_UNLIT]) + ListMatUnlit::Arguments.emplace_back(mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY); return; } @@ -220,16 +163,38 @@ void STKAnimatedMesh::render() glUseProgram(MeshShader::BubbleShader::Program); GLMesh* mesh; - for_in(mesh, TransparentMesh[TM_DEFAULT]) + if (World::getWorld() && World::getWorld()->isFogEnabled()) { - TransparentMeshes::MeshSet.push_back(mesh); - TransparentMeshes::MVPSet.push_back(AbsoluteTransformation); - } + const Track * const track = World::getWorld()->getTrack(); - for_in(mesh, TransparentMesh[TM_ADDITIVE]) + // Todo : put everything in a ubo + const float fogmax = track->getFogMax(); + const float startH = track->getFogStartHeight(); + const float endH = track->getFogEndHeight(); + const float start = track->getFogStart(); + const float end = track->getFogEnd(); + const video::SColor tmpcol = track->getFogColor(); + + video::SColorf col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + for_in(mesh, TransparentMesh[TM_DEFAULT]) + ListBlendTransparentFog::Arguments.push_back( + std::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix, + fogmax, startH, endH, start, end, col)); + for_in(mesh, TransparentMesh[TM_ADDITIVE]) + ListAdditiveTransparentFog::Arguments.push_back( + std::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix, + fogmax, startH, endH, start, end, col)); + } + else { - TransparentMeshes::MeshSet.push_back(mesh); - TransparentMeshes::MVPSet.push_back(AbsoluteTransformation); + for_in(mesh, TransparentMesh[TM_DEFAULT]) + ListBlendTransparent::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix); + + for_in(mesh, TransparentMesh[TM_ADDITIVE]) + ListAdditiveTransparent::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix); } return; } diff --git a/src/graphics/stkanimatedmesh.hpp b/src/graphics/stkanimatedmesh.hpp index 76db7786e..c5c113da0 100644 --- a/src/graphics/stkanimatedmesh.hpp +++ b/src/graphics/stkanimatedmesh.hpp @@ -11,11 +11,10 @@ class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode { protected: bool firstTime; - PtrVector GeometricMesh[FPSM_COUNT]; - PtrVector ShadedMesh[SM_COUNT]; + PtrVector MeshSolidMaterial[MAT_COUNT]; PtrVector TransparentMesh[TM_COUNT]; std::vector GLmeshes; - core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView; + core::matrix4 ModelViewProjectionMatrix; void cleanGLMeshes(); public: STKAnimatedMesh(irr::scene::IAnimatedMesh* mesh, irr::scene::ISceneNode* parent, diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index 95cbbbc19..27ae172df 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -55,7 +55,7 @@ void STKInstancedSceneNode::createGLMeshes() isMaterialInitialized = false; } -void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat) +void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh) { mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); glGenBuffers(1, &instances_vbo); @@ -99,11 +99,9 @@ void STKInstancedSceneNode::setFirstTimeMaterial() video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; GLMesh &mesh = GLmeshes[i]; - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); - initinstancedvaostate(mesh, GeometricType, ShadedType); - GeometricMesh[GeometricType].push_back(&mesh); - ShadedMesh[ShadedType].push_back(&mesh); + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); + initinstancedvaostate(mesh); + MeshSolidMaterial[MatType].push_back(&mesh); } isMaterialInitialized = true; } @@ -131,15 +129,15 @@ static void drawFSPMDefault(GLMesh &mesh, size_t instance_count) if (mesh.textures[0]) { compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + setTexture(MeshShader::InstancedObjectPass1ShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); } else { - setTexture(0, 0, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, false); + setTexture(MeshShader::InstancedObjectPass1ShaderInstance->TU_tex, 0, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, false); GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - MeshShader::InstancedObjectPass1Shader::setUniforms(0); + MeshShader::InstancedObjectPass1ShaderInstance->setUniforms(); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); @@ -158,7 +156,7 @@ static void drawShadowDefault(GLMesh &mesh, size_t instance_count) GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - MeshShader::InstancedShadowShader::setUniforms(); + MeshShader::InstancedShadowShaderInstance->setUniforms(); glBindVertexArray(mesh.vao_shadow_pass); glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count); @@ -172,8 +170,8 @@ static void drawFSPMAlphaRefTexture(GLMesh &mesh, size_t instance_count) size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::InstancedObjectRefPass1Shader::setUniforms(0); + setTexture(MeshShader::InstancedObjectRefPass1ShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedObjectRefPass1ShaderInstance->setUniforms(); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); @@ -187,8 +185,23 @@ static void drawShadowAlphaRefTexture(GLMesh &mesh, size_t instance_count) size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::InstancedRefShadowShader::setUniforms(0); + setTexture(MeshShader::InstancedRefShadowShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedRefShadowShaderInstance->setUniforms(); + + glBindVertexArray(mesh.vao_shadow_pass); + glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count); +} + +static void drawShadowGrass(GLMesh &mesh, const core::vector3df &windDir, size_t instance_count) +{ + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::InstancedGrassShadowShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedGrassShadowShaderInstance->setUniforms(windDir); glBindVertexArray(mesh.vao_shadow_pass); glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count); @@ -202,21 +215,21 @@ static void drawFSPMGrass(GLMesh &mesh, const core::vector3df &windDir, size_t i size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::InstancedGrassPass1Shader::setUniforms(windDir, 0); + setTexture(MeshShader::InstancedGrassPass1ShaderInstance->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::InstancedGrassPass1ShaderInstance->setUniforms(windDir); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } -static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count) +static void drawSMDefault(GLMesh &mesh, size_t instance_count) { irr_driver->IncreaseObjectCount(); GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - setTexture(MeshShader::InstancedObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + setTexture(MeshShader::InstancedObjectPass2ShaderInstance->TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); if (irr_driver->getLightViz()) { GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; @@ -228,13 +241,13 @@ static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjection glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY); + MeshShader::InstancedObjectPass2ShaderInstance->setUniforms(irr_driver->getSceneManager()->getAmbientLight()); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } -static void drawSMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count) +static void drawSMAlphaRefTexture(GLMesh &mesh, size_t instance_count) { irr_driver->IncreaseObjectCount(); GLenum ptype = mesh.PrimitiveType; @@ -242,7 +255,7 @@ static void drawSMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelViewPr size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(MeshShader::InstancedObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + setTexture(MeshShader::InstancedObjectRefPass2ShaderInstance->TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); if (irr_driver->getLightViz()) { GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; @@ -254,13 +267,13 @@ static void drawSMAlphaRefTexture(GLMesh &mesh, const core::matrix4 &ModelViewPr glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - MeshShader::InstancedObjectRefPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY); + MeshShader::InstancedObjectRefPass2ShaderInstance->setUniforms(irr_driver->getSceneManager()->getAmbientLight()); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } -static void drawSMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDir, size_t instance_count) +static void drawSMGrass(GLMesh &mesh, const core::vector3df &windDir, size_t instance_count) { irr_driver->IncreaseObjectCount(); GLenum ptype = mesh.PrimitiveType; @@ -268,7 +281,7 @@ static void drawSMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMa size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(MeshShader::InstancedGrassPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + setTexture(MeshShader::InstancedGrassPass2ShaderInstance->TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); if (irr_driver->getLightViz()) { GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; @@ -279,10 +292,10 @@ static void drawSMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMa GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } - setTexture(MeshShader::InstancedGrassPass2Shader::TU_dtex, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); + setTexture(MeshShader::InstancedGrassPass2ShaderInstance->TU_dtex, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST); SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT); - MeshShader::InstancedGrassPass2Shader::setUniforms(ModelViewProjectionMatrix, irr_driver->getInvViewMatrix(), irr_driver->getInvProjMatrix(), windDir, cb->getPosition()); + MeshShader::InstancedGrassPass2ShaderInstance->setUniforms(windDir, cb->getPosition(), irr_driver->getSceneManager()->getAmbientLight()); glBindVertexArray(mesh.vao); glDrawElementsInstanced(ptype, count, itype, 0, instance_count); @@ -303,54 +316,59 @@ void STKInstancedSceneNode::render() ModelViewProjectionMatrix = irr_driver->getProjMatrix(); ModelViewProjectionMatrix *= irr_driver->getViewMatrix(); - if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty()) - glUseProgram(MeshShader::InstancedObjectPass1Shader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++) - drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_DEFAULT].empty()) + glUseProgram(MeshShader::InstancedObjectPass1ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++) + drawFSPMDefault(*MeshSolidMaterial[MAT_DEFAULT][i], instance_pos.size() / 9); - if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) - glUseProgram(MeshShader::InstancedObjectRefPass1Shader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++) - drawFSPMAlphaRefTexture(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_ALPHA_REF].empty()) + glUseProgram(MeshShader::InstancedObjectRefPass1ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++) + drawFSPMAlphaRefTexture(*MeshSolidMaterial[MAT_ALPHA_REF][i], instance_pos.size() / 9); windDir = getWind(); - if (!GeometricMesh[FPSM_GRASS].empty()) - glUseProgram(MeshShader::InstancedGrassPass1Shader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_GRASS].size(); i++) - drawFSPMGrass(*GeometricMesh[FPSM_GRASS][i], windDir, instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_GRASS].empty()) + glUseProgram(MeshShader::InstancedGrassPass1ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++) + drawFSPMGrass(*MeshSolidMaterial[MAT_GRASS][i], windDir, instance_pos.size() / 9); return; } if (irr_driver->getPhase() == SOLID_LIT_PASS) { - if (!ShadedMesh[SM_DEFAULT_STANDARD].empty()) - glUseProgram(MeshShader::InstancedObjectPass2Shader::Program); - for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT_STANDARD].size(); i++) - drawSMDefault(*ShadedMesh[SM_DEFAULT_STANDARD][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_DEFAULT].empty()) + glUseProgram(MeshShader::InstancedObjectPass2ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++) + drawSMDefault(*MeshSolidMaterial[MAT_DEFAULT][i], instance_pos.size() / 9); - if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty()) - glUseProgram(MeshShader::InstancedObjectRefPass2Shader::Program); - for (unsigned i = 0; i < ShadedMesh[SM_ALPHA_REF_TEXTURE].size(); i++) - drawSMAlphaRefTexture(*ShadedMesh[SM_ALPHA_REF_TEXTURE][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_ALPHA_REF].empty()) + glUseProgram(MeshShader::InstancedObjectRefPass2ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++) + drawSMAlphaRefTexture(*MeshSolidMaterial[MAT_ALPHA_REF][i], instance_pos.size() / 9); - if (!ShadedMesh[SM_GRASS].empty()) - glUseProgram(MeshShader::InstancedGrassPass2Shader::Program); - for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++) - drawSMGrass(*ShadedMesh[SM_GRASS][i], ModelViewProjectionMatrix, windDir, instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_GRASS].empty()) + glUseProgram(MeshShader::InstancedGrassPass2ShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++) + drawSMGrass(*MeshSolidMaterial[MAT_GRASS][i], windDir, instance_pos.size() / 9); return; } if (irr_driver->getPhase() == SHADOW_PASS) { - if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty()) - glUseProgram(MeshShader::InstancedShadowShader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++) - drawShadowDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_DEFAULT].empty()) + glUseProgram(MeshShader::InstancedShadowShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++) + drawShadowDefault(*MeshSolidMaterial[MAT_DEFAULT][i], instance_pos.size() / 9); - if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) - glUseProgram(MeshShader::InstancedRefShadowShader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_ALPHA_REF_TEXTURE].size(); i++) - drawShadowAlphaRefTexture(*GeometricMesh[FPSM_ALPHA_REF_TEXTURE][i], instance_pos.size() / 9); + if (!MeshSolidMaterial[MAT_ALPHA_REF].empty()) + glUseProgram(MeshShader::InstancedRefShadowShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++) + drawShadowAlphaRefTexture(*MeshSolidMaterial[MAT_ALPHA_REF][i], instance_pos.size() / 9); + + if (!MeshSolidMaterial[MAT_GRASS].empty()) + glUseProgram(MeshShader::InstancedGrassShadowShaderInstance->Program); + for (unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++) + drawShadowGrass(*MeshSolidMaterial[MAT_GRASS][i], windDir, instance_pos.size() / 9); return; } } diff --git a/src/graphics/stkinstancedscenenode.hpp b/src/graphics/stkinstancedscenenode.hpp index 19f37abf3..5d9bbb784 100644 --- a/src/graphics/stkinstancedscenenode.hpp +++ b/src/graphics/stkinstancedscenenode.hpp @@ -8,8 +8,7 @@ class STKInstancedSceneNode : public irr::scene::CMeshSceneNode { protected: int m_ref_count; - std::vector GeometricMesh[FPSM_COUNT]; - std::vector ShadedMesh[SM_COUNT]; + std::vector MeshSolidMaterial[MAT_COUNT]; std::vector GLmeshes; std::vector instance_pos; core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView; @@ -17,7 +16,7 @@ protected: void createGLMeshes(); bool isMaterialInitialized; void setFirstTimeMaterial(); - void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat); + void initinstancedvaostate(GLMesh &mesh); void cleanGL(); core::vector3df windDir; public: diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index d24517e43..84134720e 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -9,41 +9,29 @@ #include "graphics/camera.hpp" #include "modes/world.hpp" -GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp) +MeshMaterial MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp) { + if (MaterialType == irr_driver->getShader(ES_SPHERE_MAP)) + return MAT_SPHEREMAP; if (MaterialType == irr_driver->getShader(ES_NORMAL_MAP)) - return FPSM_NORMAL_MAP; + return MAT_NORMAL_MAP; else if (MaterialType == irr_driver->getShader(ES_OBJECTPASS_REF) || MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF) - return FPSM_ALPHA_REF_TEXTURE; + return MAT_ALPHA_REF; else if (MaterialType == irr_driver->getShader(ES_GRASS) || MaterialType == irr_driver->getShader(ES_GRASS_REF)) - return FPSM_GRASS; + return MAT_GRASS; + else if (MaterialType == irr_driver->getShader(ES_SPLATTING)) + return MAT_SPLATTING; + else if (MaterialType == irr_driver->getShader(ES_OBJECT_UNLIT)) + return MAT_UNLIT; else if (tp == video::EVT_2TCOORDS) - return FPSM_DEFAULT_2TCOORD; - assert(tp == video::EVT_STANDARD); - return FPSM_DEFAULT_STANDARD; -} - -ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures, video::E_VERTEX_TYPE tp) -{ - if (type == irr_driver->getShader(ES_SPHERE_MAP)) - return SM_SPHEREMAP; - else if (type == irr_driver->getShader(ES_SPLATTING)) - return SM_SPLATTING; - else if (type == irr_driver->getShader(ES_OBJECTPASS_REF) || type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF) - return SM_ALPHA_REF_TEXTURE; - else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF)) - return SM_GRASS; - else if (type == irr_driver->getShader(ES_OBJECT_UNLIT)) - return SM_UNLIT; - else if (tp == video::EVT_2TCOORDS) - return SM_DETAILS; - else if (tp == video::EVT_TANGENTS) - return SM_DEFAULT_TANGENT; - return SM_DEFAULT_STANDARD; + return MAT_DETAIL; + return MAT_DEFAULT; } TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE type, f32 MaterialTypeParam) { + if (type == irr_driver->getShader(ES_DISPLACE)) + return TM_DISPLACEMENT; if (type == irr_driver->getShader(ES_BUBBLES)) return TM_BUBBLE; video::E_BLEND_FACTOR srcFact, DstFact; @@ -240,15 +228,6 @@ core::matrix4 computeMVP(const core::matrix4 &ModelMatrix) return ModelViewProjectionMatrix; } -core::matrix4 computeTIMV(const core::matrix4 &ModelMatrix) -{ - core::matrix4 TransposeInverseModelView = irr_driver->getViewMatrix(); - TransposeInverseModelView *= ModelMatrix; - TransposeInverseModelView.makeInverse(); - TransposeInverseModelView = TransposeInverseModelView.getTransposed(); - return TransposeInverseModelView; -} - core::vector3df getWind() { const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f; @@ -258,179 +237,6 @@ core::vector3df getWind() return m_speed * vector3df(1., 0., 0.) * cos(time); } -void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - assert(mesh.VAOType == video::EVT_STANDARD); - - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - MeshShader::GrassPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, windDir, 0); - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); -} - - -void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - // Texlayout - compressTexture(mesh.textures[1], true); - setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail0 - compressTexture(mesh.textures[2], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail1 - compressTexture(mesh.textures[3], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - compressTexture(mesh.textures[4], true); - //Tex detail2 - setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail3 - compressTexture(mesh.textures[5], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix); - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); -} - - -void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - assert(mesh.VAOType == video::EVT_STANDARD); - - if (!mesh.textures[0]) - const_cast(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::GrassPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::GrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir); - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); -} - -void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - MeshShader::TransparentShader::setUniforms(ModelViewProjectionMatrix, TextureMatrix, 0); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - const Track * const track = World::getWorld()->getTrack(); - - // This function is only called once per frame - thus no need for setters. - const float fogmax = track->getFogMax(); - const float startH = track->getFogStartHeight(); - const float endH = track->getFogEndHeight(); - const float start = track->getFogStart(); - const float end = track->getFogEnd(); - const video::SColor tmpcol = track->getFogColor(); - - core::vector3df col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - if (mesh.textures[0] != NULL) - { - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - } - - glUseProgram(MeshShader::TransparentFogShader::Program); - MeshShader::TransparentFogShader::setUniforms(ModelViewProjectionMatrix, TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix) { irr_driver->IncreaseObjectCount(); @@ -448,30 +254,6 @@ void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatr glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } -void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::RefShadowShader::setUniforms(ModelMatrix, 0); - glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex); -} - -void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - MeshShader::ShadowShader::setUniforms(ModelMatrix); - glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *) mesh.vaoOffset, 4, mesh.vaoBaseVertex); -} - bool isObject(video::E_MATERIAL_TYPE type) { if (type == irr_driver->getShader(ES_OBJECTPASS)) @@ -492,6 +274,8 @@ bool isObject(video::E_MATERIAL_TYPE type) return true; if (type == irr_driver->getShader(ES_BUBBLES)) return true; + if (type == irr_driver->getShader(ES_DISPLACE)) + return true; if (type == irr_driver->getShader(ES_OBJECT_UNLIT)) return true; if (type == video::EMT_TRANSPARENT_ALPHA_CHANNEL) @@ -509,13 +293,17 @@ bool isObject(video::E_MATERIAL_TYPE type) return false; } -void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat) -{ - mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); -} - -void initvaostate(GLMesh &mesh, TransparentMaterial TranspMat) -{ - mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); -} +std::vector > ListMatDefault::Arguments; +std::vector > ListMatAlphaRef::Arguments; +std::vector > ListMatSphereMap::Arguments; +std::vector > ListMatDetails::Arguments; +std::vector > ListMatGrass::Arguments; +std::vector > ListMatUnlit::Arguments; +std::vector > ListMatSplatting::Arguments; +std::vector > ListMatNormalMap::Arguments; +std::vector > ListBlendTransparent::Arguments; +std::vector > ListAdditiveTransparent::Arguments; +std::vector > ListBlendTransparentFog::Arguments; +std::vector > ListAdditiveTransparentFog::Arguments; +std::vector > ListDisplacement::Arguments; \ No newline at end of file diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index 70e2299fd..ca435130a 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -8,29 +8,20 @@ #include #include "../lib/irrlicht/source/Irrlicht/CMeshSceneNode.h" +#include #include -enum GeometricMaterial +enum MeshMaterial { - FPSM_DEFAULT_STANDARD, - FPSM_DEFAULT_2TCOORD, - FPSM_ALPHA_REF_TEXTURE, - FPSM_NORMAL_MAP, - FPSM_GRASS, - FPSM_COUNT -}; - -enum ShadedMaterial -{ - SM_DEFAULT_STANDARD, - SM_DEFAULT_TANGENT, - SM_ALPHA_REF_TEXTURE, - SM_SPHEREMAP, - SM_SPLATTING, - SM_GRASS, - SM_UNLIT, - SM_DETAILS, - SM_COUNT + MAT_DEFAULT, + MAT_ALPHA_REF, + MAT_NORMAL_MAP, + MAT_GRASS, + MAT_SPHEREMAP, + MAT_SPLATTING, + MAT_UNLIT, + MAT_DETAIL, + MAT_COUNT }; enum TransparentMaterial @@ -38,6 +29,7 @@ enum TransparentMaterial TM_DEFAULT, TM_ADDITIVE, TM_BUBBLE, + TM_DISPLACEMENT, TM_COUNT }; @@ -61,108 +53,95 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb); void fillLocalBuffer(GLMesh &, scene::IMeshBuffer* mb); video::E_VERTEX_TYPE getVTXTYPEFromStride(size_t stride); GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type); -void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat); -void initvaostate(GLMesh &mesh, TransparentMaterial TranspMat); core::matrix4 computeMVP(const core::matrix4 &ModelViewProjectionMatrix); -core::matrix4 computeTIMV(const core::matrix4 &TransposeInverseModelView); bool isObject(video::E_MATERIAL_TYPE type); core::vector3df getWind(); // Pass 1 shader (ie shaders that outputs normals and depth) -template -class GroupedFPSM +class ListMatDefault { public: - static std::vector MeshSet; - static std::vector MVPSet, TIMVSet; - - static void reset() - { - MeshSet.clear(); - MVPSet.clear(); - TIMVSet.clear(); - } + static std::vector > Arguments; }; -template -std::vector GroupedFPSM::MeshSet; -template -std::vector GroupedFPSM::MVPSet; -template -std::vector GroupedFPSM::TIMVSet; - - -template -void draw(const GLMesh &mesh, uniforms... Args) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - Shader::setUniforms(Args...); - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); -} - -void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir); - -// Pass 2 shader (ie shaders that outputs final color) -template -class GroupedSM +class ListMatAlphaRef { public: - static std::vector MeshSet; - static std::vector MVPSet, TIMVSet; - - static void reset() - { - MeshSet.clear(); - MVPSet.clear(); - TIMVSet.clear(); - } + static std::vector > Arguments; }; -template -std::vector GroupedSM::MeshSet; -template -std::vector GroupedSM::MVPSet; -template -std::vector GroupedSM::TIMVSet; - -void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); -void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir); - -// Shadow pass -void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix); -void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix); - -template -class TransparentMeshes +class ListMatNormalMap { public: - static std::vector MeshSet; - static std::vector MVPSet; - - static void reset() - { - MeshSet.clear(); - MVPSet.clear(); - } + static std::vector > Arguments; }; -template -std::vector TransparentMeshes::MeshSet; -template -std::vector TransparentMeshes::MVPSet; +class ListMatGrass +{ +public: + static std::vector > Arguments; +}; + +class ListMatSphereMap +{ +public: + static std::vector > Arguments; +}; + +class ListMatSplatting +{ +public: + static std::vector > Arguments; +}; + +class ListMatUnlit +{ +public: + static std::vector > Arguments; +}; + +class ListMatDetails +{ +public: + static std::vector > Arguments; +}; + + +class ListBlendTransparent +{ +public: + static std::vector > Arguments; +}; + +class ListAdditiveTransparent +{ +public: + static std::vector > Arguments; +}; + +class ListBlendTransparentFog +{ +public: + static std::vector > Arguments; +}; + +class ListAdditiveTransparentFog +{ +public: + static std::vector > Arguments; +}; + +class ListDisplacement +{ +public: + static std::vector > Arguments; +}; // Forward pass (for transparents meshes) -void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix); -void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix); void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); -GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE, video::E_VERTEX_TYPE); -ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures, video::E_VERTEX_TYPE tp); +MeshMaterial MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE, video::E_VERTEX_TYPE); TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam); #endif // STKMESH_H diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index 77b5fe308..7ce60fbf8 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -16,6 +16,7 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, const irr::core::vector3df& scale) : CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) { + isDisplacement = false; immediate_draw = false; update_each_frame = false; createGLMeshes(); @@ -48,6 +49,7 @@ void STKMeshSceneNode::setFirstTimeMaterial() scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; + video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam; video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); @@ -59,6 +61,7 @@ void STKMeshSceneNode::setFirstTimeMaterial() continue; } + GLMesh &mesh = GLmeshes[i]; if (rnd->isTransparent()) { @@ -66,7 +69,7 @@ void STKMeshSceneNode::setFirstTimeMaterial() if (immediate_draw) { fillLocalBuffer(mesh, mb); - initvaostate(mesh, TranspMat); + mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); glBindVertexArray(0); } else @@ -74,19 +77,16 @@ void STKMeshSceneNode::setFirstTimeMaterial() } else { - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); + assert(!isDisplacement); + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); if (immediate_draw) { fillLocalBuffer(mesh, mb); - initvaostate(mesh, GeometricType, ShadedType); + mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); glBindVertexArray(0); } else - { - GeometricMesh[GeometricType].push_back(&mesh); - ShadedMesh[ShadedType].push_back(&mesh); - } + MeshSolidMaterials[MatType].push_back(&mesh); } if (!immediate_draw) @@ -113,10 +113,8 @@ void STKMeshSceneNode::cleanGLMeshes() glDeleteBuffers(1, &(mesh.index_buffer)); } GLmeshes.clear(); - for (unsigned i = 0; i < FPSM_COUNT; i++) - GeometricMesh[i].clearWithoutDeleting(); - for (unsigned i = 0; i < SM_COUNT; i++) - ShadedMesh[i].clearWithoutDeleting(); + for (unsigned i = 0; i < MAT_COUNT; i++) + MeshSolidMaterials[i].clearWithoutDeleting(); } void STKMeshSceneNode::setMesh(irr::scene::IMesh* mesh) @@ -144,49 +142,6 @@ void STKMeshSceneNode::drawGlow(const GLMesh &mesh) glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } -static video::ITexture *displaceTex = 0; - -void STKMeshSceneNode::drawDisplace(const GLMesh &mesh) -{ - if (mesh.VAOType != video::EVT_2TCOORDS) - { - Log::error("Materials", "Displacement has wrong vertex type"); - return; - } - glBindVertexArray(getVAO(video::EVT_2TCOORDS)); - DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE); - - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - // Generate displace mask - // Use RTT_TMP4 as displace mask - irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind(); - - glUseProgram(MeshShader::DisplaceMaskShader::Program); - MeshShader::DisplaceMaskShader::setUniforms(AbsoluteTransformation); - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); - - // Render the effect - if (!displaceTex) - displaceTex = irr_driver->getTexture(FileManager::TEXTURE, "displace.png"); - irr_driver->getFBO(FBO_DISPLACE).Bind(); - setTexture(0, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true); - setTexture(1, irr_driver->getRenderTargetTexture(RTT_TMP1), GL_LINEAR, GL_LINEAR, true); - setTexture(2, irr_driver->getRenderTargetTexture(RTT_COLOR), GL_LINEAR, GL_LINEAR, true); - setTexture(3, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR, true); - glUseProgram(MeshShader::DisplaceShader::Program); - MeshShader::DisplaceShader::setUniforms(AbsoluteTransformation, - core::vector2df(cb->getDirX(), cb->getDirY()), - core::vector2df(cb->getDir2X(), cb->getDir2Y()), - core::vector2df(float(UserConfigParams::m_width), - float(UserConfigParams::m_height)), - 0, 1, 2, 3); - - glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); -} - void STKMeshSceneNode::updatevbo() { for (unsigned i = 0; i < Mesh->getMeshBufferCount(); ++i) @@ -222,6 +177,17 @@ void STKMeshSceneNode::updatevbo() } } +static video::ITexture *spareWhiteTex = 0; + + +void STKMeshSceneNode::OnRegisterSceneNode() +{ + if (isDisplacement) + SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); + else + CMeshSceneNode::OnRegisterSceneNode(); +} + void STKMeshSceneNode::render() { irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); @@ -229,9 +195,6 @@ void STKMeshSceneNode::render() if (!Mesh || !driver) return; - bool isTransparentPass = - SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; - ++PassCount; Box = Mesh->getBoundingBox(); @@ -246,74 +209,65 @@ void STKMeshSceneNode::render() GLmeshes[i].TextureMatrix = getMaterial(i).getTextureMatrix(0); } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS && immediate_draw) { - ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); - TransposeInverseModelView = computeTIMV(AbsoluteTransformation); core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); - if (immediate_draw) + + glDisable(GL_CULL_FACE); + if (update_each_frame) + updatevbo(); + glUseProgram(MeshShader::ObjectPass1Shader::getInstance()->Program); + // Only untextured + for (unsigned i = 0; i < GLmeshes.size(); i++) { - glDisable(GL_CULL_FACE); - if (update_each_frame) - updatevbo(); - glUseProgram(MeshShader::ObjectPass1Shader::Program); - // Only untextured - for (unsigned i = 0; i < GLmeshes.size(); i++) - { - irr_driver->IncreaseObjectCount(); - GLMesh &mesh = GLmeshes[i]; - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; + irr_driver->IncreaseObjectCount(); + GLMesh &mesh = GLmeshes[i]; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; - MeshShader::ObjectPass1Shader::setUniforms(AbsoluteTransformation, invmodel, 0); - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); - glBindVertexArray(0); - } - glEnable(GL_CULL_FACE); - return; + MeshShader::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel); + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); } + glEnable(GL_CULL_FACE); + return; + } + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) + { + core::matrix4 invmodel; + AbsoluteTransformation.getInverse(invmodel); GLMesh* mesh; - for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterials[MAT_DEFAULT]) + ListMatDefault::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterials[MAT_ALPHA_REF]) + ListMatAlphaRef::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterials[MAT_SPHEREMAP]) + ListMatSphereMap::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - for_in(mesh, GeometricMesh[FPSM_NORMAL_MAP]) - { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); - } + for_in(mesh, MeshSolidMaterials[MAT_DETAIL]) + ListMatDetails::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); - if (!GeometricMesh[FPSM_GRASS].empty()) - glUseProgram(MeshShader::GrassPass1Shader::Program); windDir = getWind(); - glBindVertexArray(getVAO(video::EVT_STANDARD)); - for_in(mesh, GeometricMesh[FPSM_GRASS]) - drawGrassPass1(*mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir); + for_in(mesh, MeshSolidMaterials[MAT_GRASS]) + ListMatGrass::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, windDir, irr_driver->getSceneManager()->getAmbientLight()); + + for_in(mesh, MeshSolidMaterials[MAT_UNLIT]) + ListMatUnlit::Arguments.emplace_back(mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY); + + for_in(mesh, MeshSolidMaterials[MAT_SPLATTING]) + ListMatSplatting::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, irr_driver->getSceneManager()->getAmbientLight()); + + for_in(mesh, MeshSolidMaterials[MAT_NORMAL_MAP]) + ListMatNormalMap::Arguments.emplace_back(mesh, AbsoluteTransformation, invmodel, core::matrix4::EM4CONST_IDENTITY, irr_driver->getSceneManager()->getAmbientLight()); return; } @@ -326,7 +280,9 @@ void STKMeshSceneNode::render() if (immediate_draw) { glDisable(GL_CULL_FACE); - glUseProgram(MeshShader::UntexturedObjectShader::Program); + if (!spareWhiteTex) + spareWhiteTex = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program); // Only untextured for (unsigned i = 0; i < GLmeshes.size(); i++) { @@ -336,7 +292,8 @@ void STKMeshSceneNode::render() GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; - MeshShader::UntexturedObjectShader::setUniforms(AbsoluteTransformation); + setTexture(MeshShader::ObjectPass2Shader::getInstance()->TU_Albedo, getTextureGLuint(spareWhiteTex), GL_NEAREST, GL_NEAREST, false); + MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, irr_driver->getSceneManager()->getAmbientLight()); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); @@ -346,62 +303,6 @@ void STKMeshSceneNode::render() return; } - GLMesh* mesh; - for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_SPHEREMAP]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_SPLATTING]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_UNLIT]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - for_in(mesh, ShadedMesh[SM_DETAILS]) - { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); - } - - if (!ShadedMesh[SM_GRASS].empty()) - glUseProgram(MeshShader::GrassPass2Shader::Program); - glBindVertexArray(getVAO(video::EVT_STANDARD)); - for_in(mesh, ShadedMesh[SM_GRASS]) - drawGrassPass2(*mesh, ModelViewProjectionMatrix, windDir); - return; } @@ -430,7 +331,7 @@ void STKMeshSceneNode::render() if (World::getWorld() && World::getWorld()->isFogEnabled()) { - glUseProgram(MeshShader::TransparentFogShader::Program); + glUseProgram(MeshShader::TransparentFogShader::getInstance()->Program); for (unsigned i = 0; i < GLmeshes.size(); i++) { GLMesh &mesh = GLmeshes[i]; @@ -449,13 +350,13 @@ void STKMeshSceneNode::render() const float end = track->getFogEnd(); const video::SColor tmpcol = track->getFogColor(); - core::vector3df col(tmpcol.getRed() / 255.0f, + video::SColorf col(tmpcol.getRed() / 255.0f, tmpcol.getGreen() / 255.0f, tmpcol.getBlue() / 255.0f); compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::TransparentFogShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); + setTexture(MeshShader::TransparentFogShader::getInstance()->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::TransparentFogShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col); assert(mesh.vao); glBindVertexArray(mesh.vao); @@ -465,7 +366,7 @@ void STKMeshSceneNode::render() } else { - glUseProgram(MeshShader::TransparentShader::Program); + glUseProgram(MeshShader::TransparentShader::getInstance()->Program); for (unsigned i = 0; i < GLmeshes.size(); i++) { irr_driver->IncreaseObjectCount(); @@ -475,9 +376,9 @@ void STKMeshSceneNode::render() size_t count = mesh.IndexCount; compressTexture(mesh.textures[0], true); - setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + setTexture(MeshShader::TransparentShader::getInstance()->TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - MeshShader::TransparentShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, 0); + MeshShader::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix); assert(mesh.vao); glBindVertexArray(mesh.vao); glDrawElements(ptype, count, itype, 0); @@ -489,17 +390,40 @@ void STKMeshSceneNode::render() GLMesh* mesh; - for_in(mesh, TransparentMesh[TM_DEFAULT]) + if (World::getWorld() && World::getWorld()->isFogEnabled()) { - TransparentMeshes::MeshSet.push_back(mesh); - TransparentMeshes::MVPSet.push_back(AbsoluteTransformation); + const Track * const track = World::getWorld()->getTrack(); + + // Todo : put everything in a ubo + const float fogmax = track->getFogMax(); + const float startH = track->getFogStartHeight(); + const float endH = track->getFogEndHeight(); + const float start = track->getFogStart(); + const float end = track->getFogEnd(); + const video::SColor tmpcol = track->getFogColor(); + + video::SColorf col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + for_in(mesh, TransparentMesh[TM_DEFAULT]) + ListBlendTransparentFog::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix, + fogmax, startH, endH, start, end, col); + for_in(mesh, TransparentMesh[TM_ADDITIVE]) + ListAdditiveTransparentFog::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix, + fogmax, startH, endH, start, end, col); + } + else + { + for_in(mesh, TransparentMesh[TM_DEFAULT]) + ListBlendTransparent::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix); + + for_in(mesh, TransparentMesh[TM_ADDITIVE]) + ListAdditiveTransparent::Arguments.emplace_back(mesh, AbsoluteTransformation, mesh->TextureMatrix); } - for_in(mesh, TransparentMesh[TM_ADDITIVE]) - { - TransparentMeshes::MeshSet.push_back(mesh); - TransparentMeshes::MVPSet.push_back(AbsoluteTransformation); - } + for_in(mesh, TransparentMesh[TM_DISPLACEMENT]) + ListDisplacement::Arguments.emplace_back(mesh, AbsoluteTransformation); if (!TransparentMesh[TM_BUBBLE].empty()) glUseProgram(MeshShader::BubbleShader::Program); @@ -508,15 +432,4 @@ void STKMeshSceneNode::render() drawBubble(*mesh, ModelViewProjectionMatrix); return; } - - if (irr_driver->getPhase() == DISPLACEMENT_PASS) - { - for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) - { - scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); - if (!mb) - continue; - drawDisplace(GLmeshes[i]); - } - } } diff --git a/src/graphics/stkmeshscenenode.hpp b/src/graphics/stkmeshscenenode.hpp index e831ce1b5..8cee51772 100644 --- a/src/graphics/stkmeshscenenode.hpp +++ b/src/graphics/stkmeshscenenode.hpp @@ -7,17 +7,15 @@ class STKMeshSceneNode : public irr::scene::CMeshSceneNode { protected: - PtrVector GeometricMesh[FPSM_COUNT]; - PtrVector ShadedMesh[SM_COUNT]; + PtrVector MeshSolidMaterials[MAT_COUNT]; PtrVector TransparentMesh[TM_COUNT]; std::vector GLmeshes; - core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView; + core::matrix4 ModelViewProjectionMatrix; core::vector3df windDir; core::vector2df caustic_dir, caustic_dir2; // Misc passes shaders (glow, displace...) void drawGlow(const GLMesh &mesh); - void drawDisplace(const GLMesh &mesh); void createGLMeshes(); void cleanGLMeshes(); void setFirstTimeMaterial(); @@ -25,6 +23,7 @@ protected: bool isMaterialInitialized; bool immediate_draw; bool update_each_frame; + bool isDisplacement; public: void setReloadEachFrame(bool); STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, @@ -33,7 +32,19 @@ public: const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f)); virtual void render(); virtual void setMesh(irr::scene::IMesh* mesh); + virtual void OnRegisterSceneNode(); virtual ~STKMeshSceneNode(); + void setIsDisplacement(bool v) { + isDisplacement = v; + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + if (isDisplacement) + mb->getMaterial().MaterialType = irr_driver->getShader(ES_DISPLACE); + } + } }; #endif diff --git a/src/guiengine/abstract_state_manager.cpp b/src/guiengine/abstract_state_manager.cpp index 3b7989370..bafed2a3a 100644 --- a/src/guiengine/abstract_state_manager.cpp +++ b/src/guiengine/abstract_state_manager.cpp @@ -140,6 +140,9 @@ void AbstractStateManager::pushScreen(Screen* screen) void AbstractStateManager::replaceTopMostScreen(Screen* screen, GUIEngine::GameState gameState) { + if (gameState == GUIEngine::CURRENT) + gameState = getGameState(); + //assert(m_game_mode != GAME); // you need to close any dialog before calling this assert(!ModalDialog::isADialogActive()); diff --git a/src/guiengine/abstract_state_manager.hpp b/src/guiengine/abstract_state_manager.hpp index b8ace0901..07f8bf8fd 100644 --- a/src/guiengine/abstract_state_manager.hpp +++ b/src/guiengine/abstract_state_manager.hpp @@ -40,7 +40,9 @@ namespace GUIEngine { MENU, GAME, - INGAME_MENU + INGAME_MENU, + /** Dummy GameState e. g. for parameters. */ + CURRENT = MENU | GAME | INGAME_MENU }; // GameState /** @@ -82,7 +84,7 @@ namespace GUIEngine * without displaying the second-topmost menu of the stack * in-between) */ - void replaceTopMostScreen(Screen* screen, GUIEngine::GameState gameState = GUIEngine::MENU); + void replaceTopMostScreen(Screen* screen, GUIEngine::GameState gameState = GUIEngine::CURRENT); /** * \brief removes the menu at the top of the screens stack diff --git a/src/guiengine/abstract_top_level_container.hpp b/src/guiengine/abstract_top_level_container.hpp index 1f7bb874f..3387f51aa 100644 --- a/src/guiengine/abstract_top_level_container.hpp +++ b/src/guiengine/abstract_top_level_container.hpp @@ -87,12 +87,9 @@ namespace GUIEngine Widget* out = getWidget(name); T* outCasted = dynamic_cast( out ); if (out != NULL && outCasted == NULL) - { - fprintf(stderr, "Screen::getWidget : Widget '%s' of type '%s'" - "cannot be casted to requested type '%s'!\n", name, - typeid(*out).name(), typeid(T).name()); - abort(); - } + Log::fatal("Screen::getWidget", "Widget '%s' of type '%s'" + "cannot be casted to requested type '%s'!\n", name, + typeid(*out).name(), typeid(T).name()); return outCasted; } diff --git a/src/guiengine/event_handler.cpp b/src/guiengine/event_handler.cpp index 217641049..3546473e5 100644 --- a/src/guiengine/event_handler.cpp +++ b/src/guiengine/event_handler.cpp @@ -608,7 +608,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event) if (w == NULL) break; - if (!w->m_focusable) return GUIEngine::EVENT_BLOCK; + if (!w->isFocusable() || !w->isActivated()) return GUIEngine::EVENT_BLOCK; // When a modal dialog is shown, don't select widgets out of the dialog if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(w)) diff --git a/src/guiengine/layout_manager.cpp b/src/guiengine/layout_manager.cpp index 32643e221..268d45605 100644 --- a/src/guiengine/layout_manager.cpp +++ b/src/guiengine/layout_manager.cpp @@ -47,7 +47,7 @@ int atoi_p(const char* val) } else { - fprintf(stderr, "[LayoutManager] WARNING: Invalid value '%s' found in XML file where integer was expected\n", val); + Log::warn("LayoutManager", "Invalid value '%s' found in XML file where integer was expected.", val); return 0; } } @@ -461,7 +461,7 @@ void LayoutManager::doCalculateLayout(PtrVector& widgets, AbstractTopLev if (left_space < 0) { - fprintf(stderr, "[LayoutManager] WARNING: statically sized widgets took all the place!!\n"); + Log::warn("LayoutManager", "Statically sized widgets took all the place!!"); left_space = 0; } @@ -536,9 +536,9 @@ void LayoutManager::doCalculateLayout(PtrVector& widgets, AbstractTopLev if (widgets[n].m_w <= 0) { - fprintf(stderr, "WARNING: widget '%s' has a width of %i (left_space = %i, " - "fraction = %f, max_width = %s)\n", widgets[n].m_properties[PROP_ID].c_str(), - widgets[n].m_w, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str()); + Log::warn("LayoutManager", "Widget '%s' has a width of %i (left_space = %i, " + "fraction = %f, max_width = %s)", widgets[n].m_properties[PROP_ID].c_str(), + widgets[n].m_w, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str()); widgets[n].m_w = 1; } @@ -556,9 +556,9 @@ void LayoutManager::doCalculateLayout(PtrVector& widgets, AbstractTopLev if (widgets[n].m_h <= 0) { - fprintf(stderr, "WARNING: widget '%s' has a height of %i (left_space = %i, " - "fraction = %f, max_width = %s)\n", widgets[n].m_properties[PROP_ID].c_str(), - widgets[n].m_h, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str()); + Log::warn("LayoutManager", "Widget '%s' has a height of %i (left_space = %i, " + "fraction = %f, max_width = %s)\n", widgets[n].m_properties[PROP_ID].c_str(), + widgets[n].m_h, left_space, fraction, widgets[n].m_properties[PROP_MAX_WIDTH].c_str()); widgets[n].m_h = 1; } diff --git a/src/guiengine/modaldialog.cpp b/src/guiengine/modaldialog.cpp index 56ab935ed..544f4c012 100644 --- a/src/guiengine/modaldialog.cpp +++ b/src/guiengine/modaldialog.cpp @@ -26,6 +26,7 @@ #include "utils/log.hpp" #include +#include using namespace irr; using namespace core; @@ -134,6 +135,8 @@ void ModalDialog::doInit() m_irrlicht_window = GUIEngine::getGUIEnv()->addWindow(m_area, true /* modal */); + m_irrlicht_window->setDrawTitlebar(false); + m_irrlicht_window->getCloseButton()->setVisible(false); GUIEngine::getSkin()->m_dialog = true; GUIEngine::getSkin()->m_dialog_size = 0.0f; diff --git a/src/guiengine/scalable_font.cpp b/src/guiengine/scalable_font.cpp index f31a933fe..17cdcb78e 100644 --- a/src/guiengine/scalable_font.cpp +++ b/src/guiengine/scalable_font.cpp @@ -57,8 +57,7 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const std::string &filename) io::IXMLReader* reader = file_manager->createXMLReader(filename.c_str()); if (!load( reader )) { - fprintf(stderr, "[ScalableFont] Loading font failed\n"); - assert(false); + Log::fatal("ScalableFont", "Loading font failed"); } reader->drop(); @@ -157,7 +156,7 @@ void ScalableFont::doReadXmlFile(io::IXMLReader* xml) #ifdef DEBUG if (m_texture_files.find(i) != m_texture_files.end()) { - fprintf(stderr, "[ScalableFont] WARNING: Font conflict, two images have texture %i\n", i); + Log::warn("ScalableFont", "Font conflict, two images have texture %i.", i); } #endif @@ -258,7 +257,7 @@ bool ScalableFont::load(io::IXMLReader* xml) { if (!SpriteBank) { - fprintf(stderr, "[ScalableFont::load] SpriteBank is NULL!!\n"); + Log::error("ScalableFont::load", "SpriteBank is NULL!!"); return false; } @@ -633,7 +632,7 @@ void ScalableFont::draw(const core::stringw& text, if (texture == NULL) { - fprintf(stderr, "WARNING: character not found in current font\n"); + Log::warn("ScalableFont", "Character not found in current font"); continue; // no such character } } @@ -709,7 +708,7 @@ void ScalableFont::lazyLoadTexture(int texID) // couldn't load texture, abort. if (!SpriteBank->getTexture(texID)) { - fprintf(stderr, "!!!!! Unable to load all textures in the font\n"); + Log::error("ScalableFont::lazyLoadTexture", "Unable to load all textures in the font"); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return; } diff --git a/src/guiengine/screen.cpp b/src/guiengine/screen.cpp index 4bc8b4e07..7adc7cf90 100644 --- a/src/guiengine/screen.cpp +++ b/src/guiengine/screen.cpp @@ -184,7 +184,7 @@ void Screen::addWidgets() Widget* w = getFirstWidget(); //std::cout << "First widget is " << (w == NULL ? "null" : w->m_properties[PROP_ID].c_str()) << std::endl; if (w != NULL) w->setFocusForPlayer( PLAYER_ID_GAME_MASTER ); - else fprintf(stderr, "Couldn't select first widget, NULL was returned\n"); + else Log::warn("Screen::AddWidgets", "Couldn't select first widget, NULL was returned"); } // addWidgets // ----------------------------------------------------------------------------- @@ -206,9 +206,9 @@ void Screen::manualRemoveWidget(Widget* w) #ifdef DEBUG if(!m_widgets.contains(w)) { - fprintf(stderr, "Widget '%d' not found in screen when removing.\n", - w->m_id); - fprintf(stderr, "This can be ignored, but is probably wrong.\n"); + Log::info("Screen", "Widget '%d' not found in screen when removing.", + w->m_id); + Log::info("Screen", "This can be ignored, but is probably wrong."); } #endif m_widgets.remove(w); diff --git a/src/guiengine/widget.hpp b/src/guiengine/widget.hpp index aa3dd5391..57eb8a1ed 100644 --- a/src/guiengine/widget.hpp +++ b/src/guiengine/widget.hpp @@ -71,7 +71,7 @@ namespace GUIEngine GAMEPAD_BADGE = 16, /** A keyboard icon */ KEYBOARD_BADGE = 32, - /** An hourglass badge to indocate loading */ + /** An hourglass badge to indicate loading */ LOADING_BADGE = 64 }; diff --git a/src/guiengine/widgets/dynamic_ribbon_widget.cpp b/src/guiengine/widgets/dynamic_ribbon_widget.cpp index aaab4685b..0ef2b97e0 100644 --- a/src/guiengine/widgets/dynamic_ribbon_widget.cpp +++ b/src/guiengine/widgets/dynamic_ribbon_widget.cpp @@ -189,7 +189,7 @@ void DynamicRibbonWidget::add() if (m_child_width <= 0 || m_child_height <= 0) { - std::cerr << "/!\\ Warning /!\\ : ribbon grid widgets require 'child_width' and 'child_height' arguments" << std::endl; + Log::warn("DynamicRibbonWidget", "Ribbon grid widgets require 'child_width' and 'child_height' arguments"); m_child_width = 256; m_child_height = 256; } @@ -206,7 +206,7 @@ void DynamicRibbonWidget::add() if (m_h - m_label_height < 0) { - fprintf(stderr, "[DynamicRibbonWidget] WARNING: the widget is too small for anything to fit in it!!\n"); + Log::warn("DynamicRibbonWidget", "The widget is too small for anything to fit in it!!"); m_row_amount = 1; } else diff --git a/src/guiengine/widgets/kart_stats_widget.cpp b/src/guiengine/widgets/kart_stats_widget.cpp index 55c40108c..fb96946ad 100644 --- a/src/guiengine/widgets/kart_stats_widget.cpp +++ b/src/guiengine/widgets/kart_stats_widget.cpp @@ -66,13 +66,9 @@ KartStatsWidget::KartStatsWidget(core::recti area, const int player_id, } if(!props) - { - fprintf(stderr, - "[KartSelectionScreen] WARNING: Can't find default " - "kart '%s' nor any other kart.\n", - default_kart.c_str()); - exit(-1); - } + Log::fatal("KartSelectionScreen", "Can't find default " + "kart '%s' nor any other kart.", + default_kart.c_str()); } diff --git a/src/guiengine/widgets/label_widget.cpp b/src/guiengine/widgets/label_widget.cpp index f7c202014..c27ec1d22 100644 --- a/src/guiengine/widgets/label_widget.cpp +++ b/src/guiengine/widgets/label_widget.cpp @@ -50,6 +50,8 @@ LabelWidget::LabelWidget(bool title, bool bright) : Widget(WTYPE_LABEL) } else m_has_color = false; + + setFocusable(false); } // LabelWidget // ---------------------------------------------------------------------------- diff --git a/src/guiengine/widgets/list_widget.cpp b/src/guiengine/widgets/list_widget.cpp index d8ed4da81..8f920dd13 100644 --- a/src/guiengine/widgets/list_widget.cpp +++ b/src/guiengine/widgets/list_widget.cpp @@ -43,6 +43,7 @@ ListWidget::ListWidget() : Widget(WTYPE_LIST) m_sort_desc = false; m_sort_default = true; m_sort_col = 0; + m_sortable = false; } // ----------------------------------------------------------------------------- @@ -270,9 +271,11 @@ std::string ListWidget::getSelectionInternalName() CGUISTKListBox* list = getIrrlichtElement(); assert(list != NULL); - if (getSelectionID() == -1 || (getSelectionID() >= (int)list->getItemCount())) + int selectionID = getSelectionID(); + if (selectionID == -1 || selectionID >= (int)list->getItemCount()) return ""; - return list->getItem(getSelectionID()).m_internal_name; + const CGUISTKListBox::ListItem& item = list->getItem(selectionID); + return item.m_internal_name; } // ----------------------------------------------------------------------------- @@ -418,6 +421,8 @@ EventPropagation ListWidget::transmitEvent(Widget* w, if (originator.find(m_properties[PROP_ID] + "_column_") != std::string::npos) { + if (!m_sortable) return EVENT_BLOCK; + if (m_sort_col != originator[(m_properties[PROP_ID] + "_column_").size()] - '0') { m_sort_desc = false; diff --git a/src/guiengine/widgets/list_widget.hpp b/src/guiengine/widgets/list_widget.hpp index 434ac1175..720032736 100644 --- a/src/guiengine/widgets/list_widget.hpp +++ b/src/guiengine/widgets/list_widget.hpp @@ -87,6 +87,8 @@ namespace GUIEngine IListWidgetHeaderListener* m_listener; + bool m_sortable; + public: typedef irr::gui::CGUISTKListBox::ListItem ListItem; typedef ListItem::ListCell ListCell; @@ -240,6 +242,8 @@ namespace GUIEngine void addColumn(irr::core::stringw col, int proportion=1) { m_header.push_back( Column(col, proportion) ); } void clearColumns() { m_header.clear(); } + + void setSortable(bool sortable) { m_sortable = sortable; } }; } diff --git a/src/guiengine/widgets/progress_bar_widget.cpp b/src/guiengine/widgets/progress_bar_widget.cpp index 10c493b2b..55c65ac7c 100644 --- a/src/guiengine/widgets/progress_bar_widget.cpp +++ b/src/guiengine/widgets/progress_bar_widget.cpp @@ -34,6 +34,7 @@ ProgressBarWidget::ProgressBarWidget(bool show_label) : Widget(WTYPE_PROGRESS) { m_value = 0; m_show_label = show_label; + setFocusable(false); } // ----------------------------------------------------------------------------- diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp index f73315ff4..3f3481288 100644 --- a/src/guiengine/widgets/ribbon_widget.cpp +++ b/src/guiengine/widgets/ribbon_widget.cpp @@ -115,8 +115,8 @@ void RibbonWidget::add() if (m_active_children[i].m_type != WTYPE_ICON_BUTTON && m_active_children[i].m_type != WTYPE_BUTTON) { - fprintf(stderr, "/!\\ Warning /!\\ : ribbon widgets can only have " - "(icon)button widgets as children\n"); + Log::warn("RiggonWidget", "Ribbon widgets can only have " + "(icon)button widgets as children"); continue; } @@ -275,7 +275,7 @@ void RibbonWidget::add() } else { - fprintf(stderr, "Invalid tab bar contents\n"); + Log::error("RibbonWidget", "Invalid tab bar contents"); } m_active_children[i].m_element = subbtn; @@ -375,8 +375,7 @@ void RibbonWidget::add() } else { - fprintf(stderr, - "/!\\ Warning /!\\ : Invalid contents type in ribbon\n"); + Log::warn("RiggonWidget", "Invalid contents type in ribbon"); } diff --git a/src/input/binding.cpp b/src/input/binding.cpp index dcac002ea..062f8172c 100644 --- a/src/input/binding.cpp +++ b/src/input/binding.cpp @@ -51,7 +51,7 @@ bool Binding::deserialize(irr::io::IrrXMLReader* xml) // Proceed only if neccesary tags were found if ((id_string == NULL) || (event_string == NULL)) { - printf("No id-string or event-string given - ignored.\n"); + Log::warn("Binding", "No id-string or event-string given - ignored."); return false; } @@ -66,7 +66,7 @@ bool Binding::deserialize(irr::io::IrrXMLReader* xml) // If the action is a stick motion & a direction is defined if (dir_string == NULL) { - printf("WARNING: IT_STICKMOTION without direction, ignoring.\n"); + Log::warn("Binding", "IT_STICKMOTION without direction, ignoring."); return false; } diff --git a/src/input/input_device.cpp b/src/input/input_device.cpp index 70278fdfe..368d71f1d 100644 --- a/src/input/input_device.cpp +++ b/src/input/input_device.cpp @@ -156,7 +156,7 @@ void GamePadDevice::resetAxisDirection(const int axis, AbstractKart* pk = player->getKart(); if (pk == NULL) { - fprintf(stderr, "Error, trying to reset axis for an unknown player\n"); + Log::error("Binding", "Trying to reset axis for an unknown player."); return; } diff --git a/src/karts/kart_properties.cpp b/src/karts/kart_properties.cpp index 68706516e..c9fb3cb4f 100644 --- a/src/karts/kart_properties.cpp +++ b/src/karts/kart_properties.cpp @@ -21,6 +21,7 @@ #include "addons/addon.hpp" #include "config/stk_config.hpp" #include "config/player_manager.hpp" +#include "graphics/glwrap.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" #include "io/file_manager.hpp" @@ -243,6 +244,11 @@ void KartProperties::load(const std::string &filename, const std::string &node) else m_minimap_icon = NULL; + if (m_minimap_icon == NULL) + { + m_minimap_icon = getUnicolorTexture(m_color); + } + // Only load the model if the .kart file has the appropriate version, // otherwise warnings are printed. if (m_version >= 1) diff --git a/src/network/client_network_manager.hpp b/src/network/client_network_manager.hpp index 422d08dc0..1c54d62dc 100644 --- a/src/network/client_network_manager.hpp +++ b/src/network/client_network_manager.hpp @@ -30,7 +30,7 @@ */ class ClientNetworkManager : public NetworkManager { - friend class Singleton; + friend class AbstractSingleton; public: /*! \brief Get the instance. * This is a utility function to avoid passing templates parameters @@ -38,7 +38,7 @@ class ClientNetworkManager : public NetworkManager */ static ClientNetworkManager* getInstance() { - return Singleton::getInstance(); + return AbstractSingleton::getInstance(); } /*! \brief Initializes network. diff --git a/src/network/network_interface.hpp b/src/network/network_interface.hpp index 1861de115..4da28b430 100644 --- a/src/network/network_interface.hpp +++ b/src/network/network_interface.hpp @@ -23,9 +23,9 @@ #ifndef NETWORK_INTERFACE_H #define NETWORK_INTERFACE_H -#include "network/singleton.hpp" #include "network/types.hpp" #include "network/network_manager.hpp" +#include "utils/singleton.hpp" #include #include @@ -33,9 +33,9 @@ /** \class NetworkInterface * \ingroup network */ -class NetworkInterface : public Singleton +class NetworkInterface : public AbstractSingleton { - friend class Singleton; + friend class AbstractSingleton; public: /*! \brief Used to init the network. diff --git a/src/network/network_manager.hpp b/src/network/network_manager.hpp index 82ff902fb..80cd42210 100644 --- a/src/network/network_manager.hpp +++ b/src/network/network_manager.hpp @@ -27,10 +27,10 @@ #include "network/stk_host.hpp" #include "network/protocol_manager.hpp" -#include "network/singleton.hpp" #include "network/types.hpp" #include "network/event.hpp" #include "network/game_setup.hpp" +#include "utils/singleton.hpp" #include @@ -43,9 +43,9 @@ * Here are defined some functions that will be specifically implemented by * the ServerNetworkManager and the ClientNetworkManager. */ -class NetworkManager : public Singleton +class NetworkManager : public AbstractSingleton { - friend class Singleton; + friend class AbstractSingleton; public: /** \brief Function to start the Network Manager (start threads) */ virtual void run(); diff --git a/src/network/network_world.hpp b/src/network/network_world.hpp index 7cbd8899c..f9b4f820f 100644 --- a/src/network/network_world.hpp +++ b/src/network/network_world.hpp @@ -22,8 +22,8 @@ #ifndef NETWORK_WORLD_HPP #define NETWORK_WORLD_HPP -#include "network/singleton.hpp" #include "input/input.hpp" +#include "utils/singleton.hpp" #include class Controller; @@ -34,9 +34,9 @@ class Item; /*! \brief Manages the world updates during an online game * This function's update is to be called instead of the normal World update */ -class NetworkWorld : public Singleton +class NetworkWorld : public AbstractSingleton { - friend class Singleton; + friend class AbstractSingleton; public: void update(float dt); diff --git a/src/network/protocol_manager.hpp b/src/network/protocol_manager.hpp index b0e55cf1b..b54b5d0e2 100644 --- a/src/network/protocol_manager.hpp +++ b/src/network/protocol_manager.hpp @@ -23,10 +23,10 @@ #ifndef PROTOCOL_MANAGER_HPP #define PROTOCOL_MANAGER_HPP -#include "network/singleton.hpp" #include "network/event.hpp" #include "network/network_string.hpp" #include "network/protocol.hpp" +#include "utils/singleton.hpp" #include "utils/types.hpp" #include @@ -102,9 +102,9 @@ typedef struct EventProcessingInfo * frames per second. Then, the management of protocols is thread-safe: any * object can start/pause/stop protocols whithout problems. */ -class ProtocolManager : public Singleton +class ProtocolManager : public AbstractSingleton { - friend class Singleton; + friend class AbstractSingleton; friend void* protocolManagerAsynchronousUpdate(void* data); public: diff --git a/src/network/protocols/get_public_address.cpp b/src/network/protocols/get_public_address.cpp index 3fe92501c..33379e71b 100644 --- a/src/network/protocols/get_public_address.cpp +++ b/src/network/protocols/get_public_address.cpp @@ -118,7 +118,7 @@ void GetPublicAddress::asynchronousUpdate() hints.ai_socktype = SOCK_STREAM; if ((status = getaddrinfo(stun_servers[rand_result].c_str(), NULL, &hints, &res)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + Log::error("getaddrinfo", gai_strerror(status)); return; } for(p = res;p != NULL; p = p->ai_next) diff --git a/src/network/server_network_manager.hpp b/src/network/server_network_manager.hpp index 1f85e879a..460cf6031 100644 --- a/src/network/server_network_manager.hpp +++ b/src/network/server_network_manager.hpp @@ -27,11 +27,11 @@ class ServerNetworkManager : public NetworkManager { - friend class Singleton; + friend class AbstractSingleton; public: static ServerNetworkManager* getInstance() { - return Singleton::getInstance(); + return AbstractSingleton::getInstance(); } virtual void run(); diff --git a/src/physics/physical_object.cpp b/src/physics/physical_object.cpp index f6a612336..57d2fa1c1 100644 --- a/src/physics/physical_object.cpp +++ b/src/physics/physical_object.cpp @@ -238,10 +238,7 @@ void PhysicalObject::init() } else { - fprintf(stderr, "[PhysicalObject] Unknown node type\n"); - max = 1.0f; - min = 0.0f; - assert(false); + Log::fatal("PhysicalObject", "Unknown node type"); } } else if (dynamic_cast(presentation) != NULL) @@ -256,10 +253,7 @@ void PhysicalObject::init() } else { - fprintf(stderr, "[PhysicalObject] Unknown node type\n"); - max = 1.0f; - min = 0.0f; - assert(false); + Log::fatal("PhysicalObject", "Unknown node type"); } Vec3 extend = max-min; // Adjust the mesth of the graphical object so that its center is where it @@ -453,7 +447,7 @@ void PhysicalObject::init() } case MP_NONE: default: - fprintf(stderr, "WARNING: Uninitialised moving shape\n"); + Log::warn("PhysicalObject", "Uninitialised moving shape"); // intended fall-through case MP_BOX: { diff --git a/src/physics/triangle_mesh.cpp b/src/physics/triangle_mesh.cpp index f8690b19c..e790950d0 100644 --- a/src/physics/triangle_mesh.cpp +++ b/src/physics/triangle_mesh.cpp @@ -112,7 +112,7 @@ void TriangleMesh::createCollisionShape(bool create_collision_object, const char btOptimizedBvh* bhv = btOptimizedBvh::deSerializeInPlace(bytes, pos, !IS_LITTLE_ENDIAN); if (bhv == NULL) { - fprintf(stderr, "[TriangleMesh] WARNING, failed to load serialized BHV\n"); + Log::warn("TriangleMesh", "Failed to load serialized BHV"); bhv_triangle_mesh = new btBvhTriangleMeshShape(&m_mesh, false /* useQuantizedAabbCompression */); } else diff --git a/src/race/grand_prix_data.cpp b/src/race/grand_prix_data.cpp index 1405e01c8..a378cd537 100644 --- a/src/race/grand_prix_data.cpp +++ b/src/race/grand_prix_data.cpp @@ -37,6 +37,9 @@ // ---------------------------------------------------------------------------- +/** Loads a grand prix definition from a file. + * \param filename Name of the file to load. + */ GrandPrixData::GrandPrixData(const std::string& filename) { m_filename = filename; @@ -44,18 +47,34 @@ GrandPrixData::GrandPrixData(const std::string& filename) StringUtils::removeExtension(filename)); m_editable = (filename.find(file_manager->getGPDir(), 0) == 0); reload(); -} +} // GrandPrixData // ---------------------------------------------------------------------------- -GrandPrixData::GrandPrixData(const unsigned int number_of_tracks, - const std::string& track_group, - const RandomGPInfoDialog::REVERSED use_reverse) +/** Creates a random grand prix from the specified parameters. + * \param number_of_tracks How many tracks to select. + * \param track_group From which track group to select the tracks. + * \param use_reverse How the reverse setting is to be determined. + * \param new_tracks If true, new tracks are selected, otherwise existing + * tracks will not be changed (used to e.g. increase the number of + * tracks in an already existing random grand prix). + * + */ +void GrandPrixData::createRandomGP(const unsigned int number_of_tracks, + const std::string &track_group, + const GPReverseType use_reverse, + bool new_tracks) { m_filename = "Random GP - Not loaded from a file!"; m_id = "random"; m_name = "Random Grand Prix"; m_editable = false; + if(new_tracks) + { + m_tracks.clear(); + m_laps.clear(); + m_reversed.clear(); + } m_tracks.reserve(number_of_tracks); m_laps.reserve(number_of_tracks); m_reversed.reserve(number_of_tracks); @@ -117,48 +136,64 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks, } // ---------------------------------------------------------------------------- - -void GrandPrixData::changeReverse(const RandomGPInfoDialog::REVERSED use_reverse) +/** Updates the GP data with newly decided reverse requirements. + * \param use_reverse How reverse setting for each track is to be determined. + */ +void GrandPrixData::changeReverse(const GrandPrixData::GPReverseType use_reverse) { for (unsigned int i = 0; i < m_tracks.size(); i++) { - if (use_reverse == RandomGPInfoDialog::NO_REVERSE) + if (use_reverse == GP_NO_REVERSE) m_reversed[i] = false; - else if (use_reverse == RandomGPInfoDialog::MIXED) + else if (use_reverse == GP_RANDOM_REVERSE) if (track_manager->getTrack(m_tracks[i])->reverseAvailable()) m_reversed[i] = (rand() % 2 != 0); else m_reversed[i] = false; else // all reversed m_reversed[i] = track_manager->getTrack(m_tracks[i])->reverseAvailable(); - } -} + } // for i < m_tracks.size() +} // changeReverse // ---------------------------------------------------------------------------- +/** Sets the id of this grand prix. + * \param id The new id. + */ void GrandPrixData::setId(const std::string& id) { m_id = id; -} +} // setId // ---------------------------------------------------------------------------- +/** Sets the name of the grand prix. + * \param name New name. + */ void GrandPrixData::setName(const irr::core::stringw& name) { m_name = name; -} +} // setName // ---------------------------------------------------------------------------- +/** Sets the filename of this grand prix. + * \param filename New filename. + */ void GrandPrixData::setFilename(const std::string& filename) { m_filename = filename; -} +} // setFilename // ---------------------------------------------------------------------------- +/** Sets if this grand prix can be edited. + * \param editable New value. + */ void GrandPrixData::setEditable(const bool editable) { m_editable = editable; -} +} // setEditable // ---------------------------------------------------------------------------- +/** Reloads grand prix from file. + */ void GrandPrixData::reload() { m_tracks.clear(); @@ -270,6 +305,8 @@ void GrandPrixData::reload() } // reload() // ---------------------------------------------------------------------------- +/** Saves the grand prix data to a file. + */ bool GrandPrixData::writeToFile() { try @@ -303,9 +340,12 @@ bool GrandPrixData::writeToFile() m_filename.c_str(), e.what()); return false; } -} +} // writeToFile // ---------------------------------------------------------------------------- +/** Checks if the grand prix data are consistent. + * \param log_error: If errors should be sent to the logger. + */ bool GrandPrixData::checkConsistency(bool log_error) const { for (unsigned int i = 0; i < m_tracks.size(); i++) @@ -323,8 +363,7 @@ bool GrandPrixData::checkConsistency(bool log_error) const } } return true; -} - +} // checkConsistency // ---------------------------------------------------------------------------- /** Returns true if the track is available. This is used to test if Fort Magma @@ -332,76 +371,99 @@ bool GrandPrixData::checkConsistency(bool log_error) const * story mode, but will be available once all challenges are done and nolok * is unlocked). It also prevents people from using the grand prix editor as * a way to play tracks that still haven't been unlocked + * \param id Name of the track to test. + * \param include_locked If set to true, all tracks (including locked tracks) + * are considered to be available. */ bool GrandPrixData::isTrackAvailable(const std::string &id, - bool includeLocked ) const + bool include_locked ) const { - if (includeLocked) + if (include_locked) return true; else if (id == "fortmagma") return !PlayerManager::getCurrentPlayer()->isLocked("fortmagma"); else return (!m_editable || !PlayerManager::get()->getCurrentPlayer()->isLocked(id)); -} +} // isTrackAvailable // ---------------------------------------------------------------------------- -std::vector GrandPrixData::getTrackNames(bool includeLocked) const +/** Returns the list of tracks that is available (i.e. unlocked) of this + * grand prix. + * \param include_locked If data for locked tracks should be included or not. + * \return A copy of the list of available tracks in this grand prix. + */ +std::vector GrandPrixData::getTrackNames(bool include_locked) const { std::vector names; for (unsigned int i = 0; i < m_tracks.size(); i++) { - if(isTrackAvailable(m_tracks[i], includeLocked)) + if(isTrackAvailable(m_tracks[i], include_locked)) names.push_back(m_tracks[i]); } return names; -} +} // getTrackNames // ---------------------------------------------------------------------------- -std::vector GrandPrixData::getLaps(bool includeLocked) const +/** Returns the laps for each available track of the grand prix. + * \param include_locked If data for locked tracks should be included or not. + * \return a std::vector containing the laps for each grand prix. + */ +std::vector GrandPrixData::getLaps(bool include_locked) const { std::vector laps; for (unsigned int i = 0; i< m_tracks.size(); i++) - if(isTrackAvailable(m_tracks[i], includeLocked)) + if(isTrackAvailable(m_tracks[i], include_locked)) laps.push_back(m_laps[i]); return laps; -} +} // getLaps // ---------------------------------------------------------------------------- -std::vector GrandPrixData::getReverse(bool includeLocked) const +/** Returns the reverse setting for each available grand prix. + * \param include_locked If data for locked tracks should be included or not. + * \return A copy of alist with the reverse status for each track. + */ +std::vector GrandPrixData::getReverse(bool include_locked) const { std::vector reverse; for (unsigned int i = 0; i< m_tracks.size(); i++) - if(isTrackAvailable(m_tracks[i], includeLocked)) + if(isTrackAvailable(m_tracks[i], include_locked)) reverse.push_back(m_reversed[i]); return reverse; -} +} // getReverse // ---------------------------------------------------------------------------- +/** Returns true if this grand prix can be edited. + */ bool GrandPrixData::isEditable() const { return m_editable; -} +} // isEditable // ---------------------------------------------------------------------------- +/** Returns the number of tracks in this grand prix. + * \param include_locked If data for locked tracks should be included or not. + */ unsigned int GrandPrixData::getNumberOfTracks(bool includeLocked) const { if (includeLocked) return m_tracks.size(); else return getTrackNames(false).size(); -} +} // getNumberOfTracks // ---------------------------------------------------------------------------- +/** Returns the (translated) name of the track with the specified index. + */ irr::core::stringw GrandPrixData::getTrackName(const unsigned int track) const { assert(track < getNumberOfTracks(true)); Track* t = track_manager->getTrack(m_tracks[track]); assert(t != NULL); return t->getName(); -} +} // getTrackName // ---------------------------------------------------------------------------- const std::string& GrandPrixData::getTrackId(const unsigned int track) const diff --git a/src/race/grand_prix_data.hpp b/src/race/grand_prix_data.hpp index 742ec15f7..ea8422e43 100644 --- a/src/race/grand_prix_data.hpp +++ b/src/race/grand_prix_data.hpp @@ -24,7 +24,6 @@ #include #include -#include "states_screens/dialogs/random_gp_dialog.hpp" #include "utils/translation.hpp" using irr::core::stringw; @@ -69,21 +68,35 @@ private: */ bool isTrackAvailable(const std::string &id, bool includeLocked) const; +public: + /** Used to define the reverse setting when creating a random GP: + * No reverse, all reverse (if available on the track), random + * selection. */ + enum GPReverseType + { + GP_NO_REVERSE = 0, + GP_ALL_REVERSE = 1, + GP_RANDOM_REVERSE = 2 + }; // GPReverseType + public: #if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__) # pragma warning(disable:4290) #endif /** Load the GrandPrixData from the given filename */ GrandPrixData(const std::string& filename); + /** Needed for simple creation of an instance of GrandPrixData */ GrandPrixData() {}; - /** Creates a new random GP */ - GrandPrixData(const unsigned int number_of_tracks, - const std::string& track_group, - const RandomGPInfoDialog::REVERSED use_reverse); + void changeTrackNumber(const unsigned int number_of_tracks, const std::string& track_group); - void changeReverse(const RandomGPInfoDialog::REVERSED use_reverse); + void changeReverse(const GPReverseType use_reverse); + + void createRandomGP(const unsigned int number_of_tracks, + const std::string& track_group, + const GPReverseType use_reverse, + bool new_tracks=false); // Methods for the GP editor void setId(const std::string& id); diff --git a/src/race/grand_prix_manager.cpp b/src/race/grand_prix_manager.cpp index 9270bac06..ce9f00b6e 100644 --- a/src/race/grand_prix_manager.cpp +++ b/src/race/grand_prix_manager.cpp @@ -34,7 +34,6 @@ const char* GrandPrixManager::SUFFIX = ".grandprix"; // ---------------------------------------------------------------------------- GrandPrixManager::GrandPrixManager() { - m_random_gp = NULL; // better do it explicitly and avoid weird stuff loadFiles(); } // GrandPrixManager @@ -42,10 +41,7 @@ GrandPrixManager::GrandPrixManager() GrandPrixManager::~GrandPrixManager() { for(unsigned int i=0; igetId() == s) diff --git a/src/race/grand_prix_manager.hpp b/src/race/grand_prix_manager.hpp index 314ddcc59..d4800204a 100644 --- a/src/race/grand_prix_manager.hpp +++ b/src/race/grand_prix_manager.hpp @@ -22,7 +22,8 @@ #include #include -#include "race/grand_prix_data.hpp" +#include "irrlicht.h" +class GrandPrixData; /** * \ingroup race @@ -47,10 +48,6 @@ private: bool existsName(const irr::core::stringw& name) const; public: - /** saved here by a random GP dialog to avoid dangling pinters or - * memory leaks */ - GrandPrixData* m_random_gp; - GrandPrixManager(); ~GrandPrixManager(); void reload(); diff --git a/src/race/highscores.cpp b/src/race/highscores.cpp index f00fd036a..4056730c3 100644 --- a/src/race/highscores.cpp +++ b/src/race/highscores.cpp @@ -212,10 +212,10 @@ void Highscores::getEntry(int number, std::string &kart_name, { if(number<0 || number>getNumberEntries()) { - fprintf(stderr, "Error, accessing undefined highscore entry:\n"); - fprintf(stderr,"number %d, but %d entries are defined\n",number, - getNumberEntries()); - fprintf(stderr, "This error can be ignored, but no highscores are available\n"); + Log::warn("Highscores", "Accessing undefined highscore entry:"); + Log::warn("Highscores", "Number %d, but %d entries are defined.", number, + getNumberEntries()); + Log::warn("Highscores", "This error can be ignored, but no highscores are available."); return; } kart_name = m_kart_name[number]; diff --git a/src/race/history.cpp b/src/race/history.cpp index f7c117f66..17cf3110e 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -127,7 +127,7 @@ void History::updateReplay(float dt) World *world = World::getWorld(); if(m_current>=(int)m_all_deltas.size()) { - printf("Replay finished.\n"); + Log::info("History", "Replay finished"); m_current = 0; // Note that for physics replay all physics parameters // need to be reset, e.g. velocity, ... @@ -158,20 +158,19 @@ void History::Save() { FILE *fd = fopen("history.dat","w"); if(fd) - printf("History saved in ./history.dat.\n"); + Log::info("History", "Saved in ./history.dat."); else { std::string fn = file_manager->getUserConfigFile("history.dat"); fd = fopen(fn.c_str(), "w"); if(fd) - printf("History saved in '%s'.\n",fn.c_str()); - + Log::info("History", "Saved in '%s'.", fn.c_str()); } if(!fd) { - printf("Can't open history.dat file for writing - can't save history.\n"); - printf("Make sure history.dat in the current directory or the config\n"); - printf("directory is writable.\n"); + Log::info("History", "Can't open history.dat file for writing - can't save history."); + Log::info("History", "Make sure history.dat in the current directory " + "or the config directory is writable."); return; } @@ -231,75 +230,46 @@ void History::Load() FILE *fd = fopen("history.dat","r"); if(fd) - printf("Reading ./history.dat\n"); + Log::info("History", "Reading ./history.dat"); else { std::string fn = file_manager->getUserConfigFile("history.dat"); fd = fopen(fn.c_str(), "r"); if(fd) - printf("Reading '%s'.\n", fn.c_str()); + Log::info("History", "Reading '%s'.", fn.c_str()); } if(!fd) - { - fprintf(stderr, "ERROR: could not open history.dat\n"); - exit(-2); - } + Log::fatal("History", "Could not open history.dat"); if (fgets(s, 1023, fd) == NULL) - { - fprintf(stderr, "ERROR: could not read history.dat\n"); - exit(-2); - } + Log::fatal("History", "Could not read history.dat."); if (sscanf(s,"Version: %1023s",s1)!=1) - { - fprintf(stderr, "ERROR: no Version information found in history file (bogus history file)\n"); - exit(-2); - } - else - { - if (strcmp(s1,STK_VERSION)) - { - fprintf(stderr, "WARNING: history is version '%s'\n",s1); - fprintf(stderr, " STK version is '%s'\n",STK_VERSION); - } - } + Log::fatal("History", "No Version information found in history file (bogus history file)."); + else if (strcmp(s1,STK_VERSION)) + Log::warn("History", "History is version '%s', STK version is '%s'.", s1, STK_VERSION); if (fgets(s, 1023, fd) == NULL) - { - fprintf(stderr, "ERROR: could not read history.dat\n"); - exit(-2); - } + Log::fatal("History", "Could not read history.dat."); unsigned int num_karts; if(sscanf(s, "numkarts: %d",&num_karts)!=1) - { - fprintf(stderr,"WARNING: No number of karts found in history file.\n"); - exit(-2); - } + Log::fatal("History", "No number of karts found in history file."); race_manager->setNumKarts(num_karts); fgets(s, 1023, fd); if(sscanf(s, "numplayers: %d",&n)!=1) - { - fprintf(stderr,"WARNING: No number of players found in history file.\n"); - exit(-2); - } + Log::fatal("History", "No number of players found in history file."); race_manager->setNumLocalPlayers(n); fgets(s, 1023, fd); if(sscanf(s, "difficulty: %d",&n)!=1) - { - fprintf(stderr,"WARNING: No difficulty found in history file.\n"); - exit(-2); - } + Log::fatal("History", "No difficulty found in history file."); race_manager->setDifficulty((RaceManager::Difficulty)n); fgets(s, 1023, fd); if(sscanf(s, "track: %1023s",s1)!=1) - { - fprintf(stderr,"WARNING: Track not found in history file.\n"); - } + Log::warn("History", "Track not found in history file."); race_manager->setTrack(s1); // This value doesn't really matter, but should be defined, otherwise // the racing phase can switch to 'ending' @@ -308,12 +278,8 @@ void History::Load() for(unsigned int i=0; igetNumPlayers()) { @@ -323,10 +289,8 @@ void History::Load() // FIXME: The model information is currently ignored fgets(s, 1023, fd); if(sscanf(s,"size: %d",&m_size)!=1) - { - fprintf(stderr,"WARNING: Number of records not found in history file.\n"); - exit(-2); - } + Log::fatal("History", "Number of records not found in history file."); + allocateMemory(m_size); m_current = -1; diff --git a/src/replay/replay_play.cpp b/src/replay/replay_play.cpp index ed3534023..a3af26002 100644 --- a/src/replay/replay_play.cpp +++ b/src/replay/replay_play.cpp @@ -88,70 +88,51 @@ void ReplayPlay::Load() FILE *fd = openReplayFile(/*writeable*/false); if(!fd) { - printf("Can't read '%s', ghost replay disabled.\n", + Log::error("Replay", "Can't read '%s', ghost replay disabled.", getReplayFilename().c_str()); destroy(); return; } - printf("Reading replay file '%s'.\n", getReplayFilename().c_str()); + Log::info("Replay", "Reading replay file '%s'.", getReplayFilename().c_str()); if (fgets(s, 1023, fd) == NULL) - { - fprintf(stderr, "ERROR: could not read '%s'.\n", - getReplayFilename().c_str()); - exit(-2); - } + Log::fatal("Replay", "Could not read '%s'.", getReplayFilename().c_str()); unsigned int version; - if (sscanf(s,"Version: %d", &version)!=1) - { - fprintf(stderr, "ERROR: no Version information found in replay file" - " (bogus replay file)\n"); - exit(-2); - } + if (sscanf(s,"Version: %d", &version) != 1) + Log::fatal("Replay", "No Version information found in replay file (bogus replay file)."); - if (version!=getReplayVersion()) + if (version != getReplayVersion()) { - fprintf(stderr, "WARNING: replay is version '%d'\n",version); - fprintf(stderr, " STK version is '%d'\n",getReplayVersion()); - fprintf(stderr, " We try to proceed, but it may fail.\n"); + Log::warn("Replay", "Replay is version '%d'",version); + Log::warn("Replay", "STK version is '%d'",getReplayVersion()); + Log::warn("Replay", "We try to proceed, but it may fail."); } if (fgets(s, 1023, fd) == NULL) - { - fprintf(stderr, "ERROR: could not read '%s'.\n", - getReplayFilename().c_str()); - exit(-2); - } + Log::fatal("Replay", "Could not read '%s'.", getReplayFilename().c_str()); int n; - if(sscanf(s, "difficulty: %d",&n)!=1) - { - fprintf(stderr,"WARNING: No difficulty found in replay file.\n"); - exit(-2); - } + if(sscanf(s, "difficulty: %d", &n) != 1) + Log::fatal("Replay", " No difficulty found in replay file."); if(race_manager->getDifficulty()!=(RaceManager::Difficulty)n) - printf("Warning, difficulty of replay is '%d', " - "while '%d' is selected.\n", - race_manager->getDifficulty(), n); + Log::warn("Replay", "Difficulty of replay is '%d', " + "while '%d' is selected.", + race_manager->getDifficulty(), n); fgets(s, 1023, fd); - if(sscanf(s, "track: %s",s1)!=1) - { - fprintf(stderr,"WARNING: Track not found in replay file.\n"); - } + if(sscanf(s, "track: %s", s1) != 1) + Log::warn("Replay", "Track not found in replay file."); assert(std::string(s1)==race_manager->getTrackName()); race_manager->setTrack(s1); unsigned int num_laps; fgets(s, 1023, fd); - if(sscanf(s, "Laps: %d",&num_laps)!=1) - { - fprintf(stderr,"WARNING: No number of laps found in replay file.\n"); - exit(-2); - } + if(sscanf(s, "Laps: %d", &num_laps) != 1) + Log::fatal("Replay", "No number of laps found in replay file."); + race_manager->setNumLaps(num_laps); // eof actually doesn't trigger here, since it requires first to try @@ -175,25 +156,18 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line) { char s[1024]; if(sscanf(next_line, "model: %s", s)!=1) - { - fprintf(stderr, - "WARNING: No model information for kart %d found.\n", + Log::fatal("Replay", "No model information for kart %d found.", m_ghost_karts.size()); - exit(-2); - } + m_ghost_karts.push_back(new GhostKart(std::string(s))); m_ghost_karts[m_ghost_karts.size()-1].init(RaceManager::KT_GHOST); fgets(s, 1023, fd); unsigned int size; if(sscanf(s,"size: %d",&size)!=1) - { - fprintf(stderr, - "WARNING: Number of records not found in replay file " - "for kart %d.\n", + Log::fatal("Replay", "Number of records not found in replay file " + "for kart %d.", m_ghost_karts.size()-1); - exit(-2); - } for(unsigned int i=0; igetIdent().c_str()); + Log::warn("ReplayRecorder", buffer); + } continue; } TransformEvent *p = &(m_transform_events[i][m_count_transforms[i]-1]); @@ -153,12 +157,12 @@ void ReplayRecorder::Save() FILE *fd = openReplayFile(/*writeable*/true); if(!fd) { - printf("Can't open '%s' for writing - can't save replay data.\n", - getReplayFilename().c_str()); + Log::error("ReplayRecorder", "Can't open '%s' for writing - can't save replay data.", + getReplayFilename().c_str()); return; } - printf("Replay saved in '%s'.\n", getReplayFilename().c_str()); + Log::info("ReplayRecorder", "Replay saved in '%s'.\n", getReplayFilename().c_str()); World *world = World::getWorld(); unsigned int num_karts = world->getNumKarts(); diff --git a/src/states_screens/credits.cpp b/src/states_screens/credits.cpp index 4927175d9..019aa3476 100644 --- a/src/states_screens/credits.cpp +++ b/src/states_screens/credits.cpp @@ -85,7 +85,7 @@ bool CreditsScreen::getWideLine(std::ifstream& file, core::stringw* out) { if (!file.good()) { - fprintf(stderr, "getWideLine : File is not good!\n"); + Log::error("CreditsScreen", "getWideLine: File is not good!"); return false; } wchar_t wide_char; @@ -147,8 +147,8 @@ void CreditsScreen::loadedFromFile() if (file.fail() || !file.is_open() || file.eof()) { - fprintf(stderr, "\n/!\\ Failed to open file at '%s'\n\n", - creditsfile.c_str()); + Log::error("CreditsScreen", "Failed to open file at '%s'.", + creditsfile.c_str()); return; } @@ -160,10 +160,8 @@ void CreditsScreen::loadedFromFile() if (file.fail() || !file.is_open() || file.eof()) { - fprintf(stderr, - "\n/!\\ Failed to read file at '%s', unexpected EOF\n\n", - creditsfile.c_str()); - assert(false); + Log::error("CreditsScreen", "Failed to read file at '%s', unexpected EOF.", + creditsfile.c_str()); return; } @@ -203,9 +201,7 @@ void CreditsScreen::loadedFromFile() if (lineCount == 0) { - fprintf(stderr, - "\n/!\\ Could not read anything from CREDITS file!\n\n"); - assert(false); + Log::error("CreditsScreen", "Could not read anything from CREDITS file!"); return; } diff --git a/src/states_screens/dialogs/addons_loading.cpp b/src/states_screens/dialogs/addons_loading.cpp index 2d6f1ef2d..1d82e4b13 100644 --- a/src/states_screens/dialogs/addons_loading.cpp +++ b/src/states_screens/dialogs/addons_loading.cpp @@ -384,11 +384,10 @@ void AddonsLoading::doUninstall() error = !addons_manager->uninstall(m_addon); if(error) { - printf("[addons]Directory '%s' can not be removed.\n", - m_addon.getDataDir().c_str()); - printf("[addons]Please remove this directory manually.\n"); - core::stringw msg = StringUtils::insertValues( - _("Problems removing the addon '%s'."), + Log::warn("Addons", "Directory '%s' can not be removed.", + m_addon.getDataDir().c_str()); + Log::warn("Addons", "Please remove this directory manually."); + core::stringw msg = StringUtils::insertValues(_("Problems removing the addon '%s'."), core::stringw(m_addon.getName().c_str())); getWidget("description")->setText(msg.c_str()); } diff --git a/src/states_screens/dialogs/custom_video_settings.cpp b/src/states_screens/dialogs/custom_video_settings.cpp index f5c270d7c..2be8a7eb2 100644 --- a/src/states_screens/dialogs/custom_video_settings.cpp +++ b/src/states_screens/dialogs/custom_video_settings.cpp @@ -102,29 +102,19 @@ GUIEngine::EventPropagation CustomVideoSettingsDialog::processEvent(const std::s { if (eventSource == "close") { - bool dynamic_light = getWidget("dynamiclight")->getState(); - UserConfigParams::m_dynamic_lights = dynamic_light; + bool advanced_pipeline = getWidget("dynamiclight")->getState(); + UserConfigParams::m_dynamic_lights = advanced_pipeline; - UserConfigParams::m_graphical_effects = - getWidget("anim_gfx")->getState(); - UserConfigParams::m_weather_effects = - getWidget("weather_gfx")->getState(); - UserConfigParams::m_ubo_disabled = - !getWidget("ubo")->getState(); UserConfigParams::m_dof = - getWidget("dof")->getState(); - UserConfigParams::m_high_definition_textures = - getWidget("hd-textures")->getState(); - + advanced_pipeline && getWidget("dof")->getState(); + UserConfigParams::m_motionblur = - getWidget("motionblur")->getState(); - UserConfigParams::m_show_steering_animations = - getWidget("steering_animations")->getValue(); - - if (dynamic_light) + advanced_pipeline && getWidget("motionblur")->getState(); + + if (advanced_pipeline) { UserConfigParams::m_shadows = - getWidget("shadows")->getValue(); + advanced_pipeline && getWidget("shadows")->getValue(); } else { @@ -132,26 +122,41 @@ GUIEngine::EventPropagation CustomVideoSettingsDialog::processEvent(const std::s } UserConfigParams::m_mlaa = - getWidget("mlaa")->getState(); + advanced_pipeline && getWidget("mlaa")->getState(); UserConfigParams::m_ssao = - getWidget("ssao")->getState(); + advanced_pipeline && getWidget("ssao")->getState(); UserConfigParams::m_light_shaft = - getWidget("lightshaft")->getState(); + advanced_pipeline && getWidget("lightshaft")->getState(); UserConfigParams::m_gi = - getWidget("global_illumination")->getState(); + advanced_pipeline && getWidget("global_illumination")->getState(); UserConfigParams::m_glow = - getWidget("glow")->getState(); + advanced_pipeline && getWidget("glow")->getState(); UserConfigParams::m_bloom = - getWidget("bloom")->getState(); + advanced_pipeline && getWidget("bloom")->getState(); UserConfigParams::m_texture_compression = getWidget("texture_compression")->getState(); + UserConfigParams::m_graphical_effects = + getWidget("anim_gfx")->getState(); + + UserConfigParams::m_weather_effects = + getWidget("weather_gfx")->getState(); + + UserConfigParams::m_ubo_disabled = + !getWidget("ubo")->getState(); + + UserConfigParams::m_high_definition_textures = + getWidget("hd-textures")->getState(); + + UserConfigParams::m_show_steering_animations = + getWidget("steering_animations")->getValue(); + switch (getWidget("filtering")->getValue()) { case 0: diff --git a/src/states_screens/dialogs/gp_info_dialog.cpp b/src/states_screens/dialogs/gp_info_dialog.cpp index 36fc61646..79ad221ca 100644 --- a/src/states_screens/dialogs/gp_info_dialog.cpp +++ b/src/states_screens/dialogs/gp_info_dialog.cpp @@ -53,8 +53,8 @@ GPInfoDialog::GPInfoDialog(const std::string& gp_ident) doInit(); m_curr_time = 0.0f; - m_gp = grand_prix_manager->getGrandPrix(gp_ident); - m_gp->checkConsistency(); + m_gp = *grand_prix_manager->getGrandPrix(gp_ident); + m_gp.checkConsistency(); m_under_title = m_area.getHeight()/7; m_over_body = m_area.getHeight()/7; @@ -72,7 +72,7 @@ GPInfoDialog::~GPInfoDialog() { GUIEngine::Screen* curr_screen = GUIEngine::getCurrentScreen(); if (curr_screen->getName() == "tracks.stkgui") - static_cast(curr_screen)->setFocusOnGP(m_gp->getId()); + static_cast(curr_screen)->setFocusOnGP(m_gp.getId()); } // ---------------------------------------------------------------------------- @@ -81,7 +81,7 @@ void GPInfoDialog::addTitle() { core::rect< s32 > area_top(0, 0, m_area.getWidth(), m_under_title); IGUIStaticText* title = GUIEngine::getGUIEnv()->addStaticText( - translations->fribidize(m_gp->getName()), + translations->fribidize(m_gp.getName()), area_top, false, true, // border, word wrap m_irrlicht_window); title->setTabStop(false); @@ -92,7 +92,7 @@ void GPInfoDialog::addTitle() void GPInfoDialog::addTracks() { - const std::vector tracks = m_gp->getTrackNames(); + const std::vector tracks = m_gp.getTrackNames(); const unsigned int track_amount = tracks.size(); int height_of_one_line = std::min((m_lower_bound - m_over_body)/(track_amount+1), @@ -119,7 +119,7 @@ void GPInfoDialog::addTracks() Label* widget = dynamic_cast(m_widgets.get(widgets_iter)); widget->setText(translations->fribidize(track->getName()), false); - widget->move(20, m_over_body + height_of_one_line*(i+1), + widget->move(20, m_over_body + height_of_one_line*i, m_area.getWidth()/2 - 20, height_of_one_line); widgets_iter++; @@ -141,7 +141,7 @@ void GPInfoDialog::addTracks() m_widgets.push_back(widget); widget->add(); - widget->move(20, m_over_body + height_of_one_line*(i+1), + widget->move(20, m_over_body + height_of_one_line*i, m_area.getWidth()/2 - 20, height_of_one_line); } } @@ -185,7 +185,7 @@ void GPInfoDialog::addScreenshot() m_screenshot_widget->m_h = m_area.getWidth()*3/8; // *(3/4)*(1/2) } - Track* track = track_manager->getTrack(m_gp->getTrackNames()[0]); + Track* track = track_manager->getTrack(m_gp.getTrackNames()[0]); m_screenshot_widget->m_properties[GUIEngine::PROP_ICON] = (track->getScreenshotFile().c_str()); m_screenshot_widget->setParent(m_irrlicht_window); m_screenshot_widget->add(); @@ -203,7 +203,7 @@ void GPInfoDialog::addButtons() SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP( StateManager::get() ->getActivePlayerProfile(0) ->getUniqueID(), - m_gp->getId(), + m_gp.getId(), race_manager->getDifficulty(), race_manager->getNumberOfKarts(), race_manager->getNumLocalPlayers()); @@ -250,7 +250,7 @@ void GPInfoDialog::addButtons() void GPInfoDialog::onEnterPressedInternal() { // Save the GP id because dismiss() will destroy this instance - std::string gp_id = m_gp->getId(); + std::string gp_id = m_gp.getId(); ModalDialog::dismiss(); // Disable accidentally unlocking of a challenge PlayerManager::getCurrentPlayer()->setCurrentChallenge(""); @@ -259,15 +259,19 @@ void GPInfoDialog::onEnterPressedInternal() // ---------------------------------------------------------------------------- -GUIEngine::EventPropagation GPInfoDialog::processEvent(const std::string& eventSource) +GUIEngine::EventPropagation GPInfoDialog::processEvent(const std::string& event_source) { - if (eventSource == "start" || eventSource == "continue") + if (event_source == "start" || event_source == "continue") { // Save GP identifier, since dismiss will delete this object. - std::string gp_id = m_gp->getId(); + std::string gp_id = m_gp.getId(); + // Also create a copy of the string: it is a reference to data + // in a widget in the dialog - so if we call dismiss, this reference + // becomes invalid! + std::string save_source = event_source; ModalDialog::dismiss(); race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, - (eventSource == "continue")); + (save_source == "continue")); return GUIEngine::EVENT_BLOCK; } @@ -284,7 +288,7 @@ void GPInfoDialog::onUpdate(float dt) m_curr_time += dt; int frameAfter = (int)(m_curr_time / 1.5f); - const std::vector tracks = m_gp->getTrackNames(); + const std::vector tracks = m_gp.getTrackNames(); if (frameAfter >= (int)tracks.size()) { frameAfter = 0; diff --git a/src/states_screens/dialogs/gp_info_dialog.hpp b/src/states_screens/dialogs/gp_info_dialog.hpp index d221d44d9..93158162e 100644 --- a/src/states_screens/dialogs/gp_info_dialog.hpp +++ b/src/states_screens/dialogs/gp_info_dialog.hpp @@ -20,7 +20,7 @@ #define HEADER_GP_INFO_DIALOG_HPP #include "guiengine/modaldialog.hpp" -// Don't include grand_prix_data.hpp here or the compilation will fail +#include "race/grand_prix_data.hpp" class GrandPrixData; @@ -39,7 +39,9 @@ class GPInfoDialog : public GUIEngine::ModalDialog protected: // Necessary for RandomGPInfoDialog GUIEngine::IconButtonWidget* m_screenshot_widget; float m_curr_time; - GrandPrixData* m_gp; + + /** The grand prix data. */ + GrandPrixData m_gp; /** height of the separator over the body */ int m_over_body; diff --git a/src/states_screens/dialogs/random_gp_dialog.cpp b/src/states_screens/dialogs/random_gp_dialog.cpp index 5a7406e5e..dbb98f219 100644 --- a/src/states_screens/dialogs/random_gp_dialog.cpp +++ b/src/states_screens/dialogs/random_gp_dialog.cpp @@ -33,11 +33,12 @@ using irr::gui::IGUIStaticText; typedef GUIEngine::SpinnerWidget Spinner; RandomGPInfoDialog::RandomGPInfoDialog() + { // Defaults - loading selection from last time frrom a file would be better m_number_of_tracks = 2; // We can assume that there are at least 2 standard tracks m_trackgroup = "standard"; - m_use_reverse = NO_REVERSE; + m_use_reverse = GrandPrixData::GP_NO_REVERSE; doInit(); m_curr_time = 0.0f; @@ -46,14 +47,7 @@ RandomGPInfoDialog::RandomGPInfoDialog() m_over_body = m_area.getHeight()/7 + SPINNER_HEIGHT + 10; // 10px space m_lower_bound = m_area.getHeight()*6/7; - // The GP manager is be used to make the GP live longer than this dialog - if (grand_prix_manager->m_random_gp) - { - delete grand_prix_manager->m_random_gp; - grand_prix_manager->m_random_gp = NULL; - } - m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse); - grand_prix_manager->m_random_gp = m_gp; + m_gp.createRandomGP(m_number_of_tracks, m_trackgroup, m_use_reverse); addTitle(); addSpinners(); @@ -67,8 +61,18 @@ RandomGPInfoDialog::RandomGPInfoDialog() void RandomGPInfoDialog::addSpinners() { - const int trackgroup_width = 200, laps_with = 150, reverse_width = 200; - const int left = (m_area.getWidth() - trackgroup_width - 150 - 250)/2; + const int laps_width = 150; + // "20*4" because there a 4 separators between the spinners with 20px each + int label_spinner_width = m_area.getWidth() - laps_width - 20*4; + // This scaling ensures that the spinners are smaller than the available + // area, look well and are (hopefully) big enough for their labels + if (m_area.getWidth() < 700) + label_spinner_width /= 2; + else if (m_area.getWidth() < 1500) + label_spinner_width /= 3; + else + label_spinner_width /= 4; + const int left = (m_area.getWidth() - label_spinner_width*2 - laps_width)/2; // Trackgroup chooser Spinner* spinner = new Spinner(false); @@ -77,7 +81,7 @@ void RandomGPInfoDialog::addSpinners() spinner->setParent(m_irrlicht_window); m_widgets.push_back(spinner); spinner->add(); - spinner->move(left, m_under_title, trackgroup_width, SPINNER_HEIGHT); + spinner->move(left, m_under_title, label_spinner_width, SPINNER_HEIGHT); // Fill it with all the track group names spinner->addLabel("all"); int index_standard; @@ -106,7 +110,7 @@ void RandomGPInfoDialog::addSpinners() spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true"; m_widgets.push_back(spinner); spinner->add(); - spinner->move(left + trackgroup_width + 10, m_under_title, laps_with, SPINNER_HEIGHT); + spinner->move(left + label_spinner_width + 20/2, m_under_title, laps_width, SPINNER_HEIGHT); // reverse choose spinner = new Spinner(false); @@ -115,7 +119,7 @@ void RandomGPInfoDialog::addSpinners() spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true"; m_widgets.push_back(spinner); spinner->add(); - spinner->move(left + trackgroup_width + laps_with + 10, m_under_title, reverse_width, SPINNER_HEIGHT); + spinner->move(left + label_spinner_width + laps_width + 20/2, m_under_title, label_spinner_width, SPINNER_HEIGHT); spinner->addLabel("no reverse"); spinner->addLabel("all reverse"); spinner->addLabel("mixed"); @@ -141,15 +145,17 @@ GUIEngine::EventPropagation RandomGPInfoDialog::processEvent( { if (eventSource == "start") { + // Save GP data, since dismiss will delete this object. + GrandPrixData gp = m_gp; ModalDialog::dismiss(); - race_manager->startGP(grand_prix_manager->m_random_gp, false, false); + race_manager->startGP(&gp, false, false); return GUIEngine::EVENT_BLOCK; } else if (eventSource == "Number of tracks") { // The old gp can be reused because there's only track deletion/adding m_number_of_tracks = getWidget("Number of tracks")->getValue(); - m_gp->changeTrackNumber(m_number_of_tracks, m_trackgroup); + m_gp.changeTrackNumber(m_number_of_tracks, m_trackgroup); addTracks(); } else if (eventSource == "Trackgroup") @@ -171,22 +177,22 @@ GUIEngine::EventPropagation RandomGPInfoDialog::processEvent( if (s->getValue() > (signed)max) s->setValue(max); - delete m_gp; - m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse); - grand_prix_manager->m_random_gp = m_gp; + // Create a new (i.e. with new tracks) random gp, since the old + // tracks might not all belong to the newly selected group. + m_gp.createRandomGP(m_number_of_tracks, m_trackgroup, m_use_reverse, + /*new_tracks*/true); addTracks(); } else if (eventSource == "reverse") { Spinner* r = getWidget("reverse"); - m_use_reverse = static_cast(r->getValue()); - m_gp->changeReverse(m_use_reverse); + m_use_reverse = static_cast(r->getValue()); + m_gp.changeReverse(m_use_reverse); } else if (eventSource == "reload") { - delete m_gp; - m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse); - grand_prix_manager->m_random_gp = m_gp; + m_gp.createRandomGP(m_number_of_tracks, m_trackgroup, m_use_reverse, + /*new_tracks*/true); addTracks(); } diff --git a/src/states_screens/dialogs/random_gp_dialog.hpp b/src/states_screens/dialogs/random_gp_dialog.hpp index 698217eec..35a058825 100644 --- a/src/states_screens/dialogs/random_gp_dialog.hpp +++ b/src/states_screens/dialogs/random_gp_dialog.hpp @@ -24,17 +24,15 @@ class RandomGPInfoDialog : public GPInfoDialog { -public: - enum REVERSED - { - NO_REVERSE = 0, - ALL_REVERSE = 1, - MIXED = 2 - }; private: + /** How many tracks to pick. */ unsigned int m_number_of_tracks; + + /** Name of the track group from which to pick tracks. */ std::string m_trackgroup; - REVERSED m_use_reverse; + + /** How reverse settings should be determined. */ + GrandPrixData::GPReverseType m_use_reverse; public: static const int SPINNER_HEIGHT = 40; diff --git a/src/states_screens/feature_unlocked.cpp b/src/states_screens/feature_unlocked.cpp index 2fc48313d..32510f341 100644 --- a/src/states_screens/feature_unlocked.cpp +++ b/src/states_screens/feature_unlocked.cpp @@ -493,7 +493,7 @@ void FeatureUnlockedCutScene::onUpdate(float dt) if (m_global_time > GIFT_EXIT_TO) { - const irr::video::SColor color2(255, 255, 126, 21); + const irr::video::SColor color2(255, 0, 0, 0); const int fontH = GUIEngine::getFontHeight(); const int MARGIN = 10; diff --git a/src/states_screens/grand_prix_lose.cpp b/src/states_screens/grand_prix_lose.cpp index f9bc459fd..27673542b 100644 --- a/src/states_screens/grand_prix_lose.cpp +++ b/src/states_screens/grand_prix_lose.cpp @@ -252,9 +252,9 @@ void GrandPrixLose::setKarts(std::vector ident_arg) } else { - fprintf(stderr, "[GrandPrixLose] WARNING: could not find a kart named '%s'\n", ident_arg[n].c_str()); + Log::warn("GrandPrixLose", "Could not find a kart named '%s'.", ident_arg[n].c_str()); m_kart_node[n] = NULL; - }// if kart !=NULL + } // if kart != NULL } } // setKarts diff --git a/src/states_screens/help_screen_1.cpp b/src/states_screens/help_screen_1.cpp index 2323be697..6a4ae514c 100644 --- a/src/states_screens/help_screen_1.cpp +++ b/src/states_screens/help_screen_1.cpp @@ -71,8 +71,8 @@ void HelpScreen1::eventCallback(Widget* widget, const std::string& name, const i if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL) { - fprintf(stderr, "[MainMenuScreen] WARNING: cannot find kart '%s', will revert to default\n", - UserConfigParams::m_default_kart.c_str()); + Log::warn("HelpScreen1", "Cannot find kart '%s', will revert to default", + UserConfigParams::m_default_kart.c_str()); UserConfigParams::m_default_kart.revertToDefaults(); } race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart); @@ -89,13 +89,19 @@ void HelpScreen1::eventCallback(Widget* widget, const std::string& name, const i } else if (name == "category") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - //if (selection == "page1") StateManager::get()->replaceTopMostScreen(Help1Screen::getInstance()); - //else - if (selection == "page2") StateManager::get()->replaceTopMostScreen(HelpScreen2::getInstance()); - else if (selection == "page3") StateManager::get()->replaceTopMostScreen(HelpScreen3::getInstance()); - else if (selection == "page4") StateManager::get()->replaceTopMostScreen(HelpScreen4::getInstance()); + Screen *screen = NULL; + //if (selection == "page1") + // screen = HelpScreen1::getInstance(); + if (selection == "page2") + screen = HelpScreen2::getInstance(); + else if (selection == "page3") + screen = HelpScreen3::getInstance(); + else if (selection == "page4") + screen = HelpScreen4::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "back") { diff --git a/src/states_screens/help_screen_2.cpp b/src/states_screens/help_screen_2.cpp index f3c751474..b2b08a0a1 100644 --- a/src/states_screens/help_screen_2.cpp +++ b/src/states_screens/help_screen_2.cpp @@ -46,12 +46,19 @@ void HelpScreen2::eventCallback(Widget* widget, const std::string& name, const i { if (name == "category") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if(selection == "page1") StateManager::get()->replaceTopMostScreen(HelpScreen1::getInstance()); - //else if(selection == "page2") StateManager::get()->replaceTopMostScreen(HelpScreen2::getInstance()); - else if(selection == "page3") StateManager::get()->replaceTopMostScreen(HelpScreen3::getInstance()); - else if(selection == "page4") StateManager::get()->replaceTopMostScreen(HelpScreen4::getInstance()); + Screen *screen = NULL; + if (selection == "page1") + screen = HelpScreen1::getInstance(); + //else if (selection == "page2") + // screen = HelpScreen2::getInstance(); + else if (selection == "page3") + screen = HelpScreen3::getInstance(); + else if (selection == "page4") + screen = HelpScreen4::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "back") { diff --git a/src/states_screens/help_screen_3.cpp b/src/states_screens/help_screen_3.cpp index 35693dd94..a8a7cb4f6 100644 --- a/src/states_screens/help_screen_3.cpp +++ b/src/states_screens/help_screen_3.cpp @@ -47,12 +47,20 @@ void HelpScreen3::eventCallback(Widget* widget, const std::string& name, const i { if (name == "category") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "page1") StateManager::get()->replaceTopMostScreen(HelpScreen1::getInstance()); - else if (selection == "page2") StateManager::get()->replaceTopMostScreen(HelpScreen2::getInstance()); - //else if(selection == "page3") StateManager::get()->replaceTopMostScreen(Help3Screen::getInstance()); - else if(selection == "page4") StateManager::get()->replaceTopMostScreen(HelpScreen4::getInstance()); + Screen *screen = NULL; + if (selection == "page1") + screen = HelpScreen1::getInstance(); + else if (selection == "page2") + screen = HelpScreen2::getInstance(); + //else if (selection == "page3") + // screen = HelpScreen3::getInstance(); + else if (selection == "page4") + screen = HelpScreen4::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "back") { diff --git a/src/states_screens/help_screen_4.cpp b/src/states_screens/help_screen_4.cpp index 97ddf3809..c271467db 100644 --- a/src/states_screens/help_screen_4.cpp +++ b/src/states_screens/help_screen_4.cpp @@ -47,11 +47,20 @@ void HelpScreen4::eventCallback(Widget* widget, const std::string& name, const i { if (name == "category") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "page1") StateManager::get()->replaceTopMostScreen(HelpScreen1::getInstance()); - else if (selection == "page2") StateManager::get()->replaceTopMostScreen(HelpScreen2::getInstance()); - else if(selection == "page3") StateManager::get()->replaceTopMostScreen(HelpScreen3::getInstance()); + Screen *screen = NULL; + if (selection == "page1") + screen = HelpScreen1::getInstance(); + else if (selection == "page2") + screen = HelpScreen2::getInstance(); + else if (selection == "page3") + screen = HelpScreen3::getInstance(); + //else if (selection == "page4") + // screen = HelpScreen4::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "back") { diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp index 93695466e..c32dc85ca 100644 --- a/src/states_screens/kart_selection.cpp +++ b/src/states_screens/kart_selection.cpp @@ -117,7 +117,6 @@ void FocusDispatcher::add() m_element->setTabStop(true); m_element->setTabGroup(false); m_element->setTabOrder(m_id); - m_element->setVisible(false); } static FocusDispatcher* g_dispatcher = NULL; @@ -332,13 +331,9 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent, } if(!props) - { - fprintf(stderr, - "[KartSelectionScreen] WARNING: Can't find default " - "kart '%s' nor any other kart.\n", - default_kart.c_str()); - exit(-1); - } + Log::fatal("KartSelectionScreen", "Can't find default " + "kart '%s' nor any other kart.", + default_kart.c_str()); } m_kartInternalName = props->getIdent(); @@ -424,14 +419,12 @@ void PlayerKartWidget::setPlayerID(const int newPlayerID) if (StateManager::get()->getActivePlayer(newPlayerID) != m_associated_player) { - Log::warn("[KartSelectionScreen]", "Internal " - "inconsistency, PlayerKartWidget has IDs and " - "pointers that do not correspond to one player"); - fprintf(stderr, - " Player: %p - Index: %d - m_associated_player: %p\n", - StateManager::get()->getActivePlayer(newPlayerID), - newPlayerID, m_associated_player); - assert(false); + Log::error("KartSelectionScreen", "Internal " + "inconsistency, PlayerKartWidget has IDs and " + "pointers that do not correspond to one player"); + Log::fatal("KartSelectionScreen", " Player: %p - Index: %d - m_associated_player: %p", + StateManager::get()->getActivePlayer(newPlayerID), + newPlayerID, m_associated_player); } // Remove current focus, but rembmer it @@ -1613,11 +1606,9 @@ void KartSelectionScreen::updateKartWidgetModel(uint8_t widget_id, ->setText( selectionText.c_str(), false ); } else - { - fprintf(stderr, "[KartSelectionScreen] WARNING: could not " - "find a kart named '%s'\n", - selection.c_str()); - } + Log::warn("KartSelectionScreen", "could not " + "find a kart named '%s'", + selection.c_str()); } } diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index e3e6c69bb..45a038b11 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -302,7 +302,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, const_cast( kart_properties_manager->getKart("tux") ), - L"Unlocked" + L"You unlocked " ); scene->addUnlockedTrack(track_manager->getTrack("lighthouse")); StateManager::get()->pushScreen(scene); @@ -323,7 +323,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, track_manager->getTrack("snowmountain") ->getScreenshotFile().c_str())); - scene->addUnlockedPictures(textures, 4.0, 3.0, L"You did it"); + scene->addUnlockedPictures(textures, 4.0, 3.0, L"You unlocked "); StateManager::get()->pushScreen(scene); } @@ -380,8 +380,8 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL) { - fprintf(stderr, "[MainMenuScreen] WARNING: cannot find kart '%s', will revert to default\n", - UserConfigParams::m_default_kart.c_str()); + Log::warn("MainMenuScreen", "Cannot find kart '%s', will revert to default", + UserConfigParams::m_default_kart.c_str()); UserConfigParams::m_default_kart.revertToDefaults(); } race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart); diff --git a/src/states_screens/options_screen_audio.cpp b/src/states_screens/options_screen_audio.cpp index 10df8ed22..1cad3443e 100644 --- a/src/states_screens/options_screen_audio.cpp +++ b/src/states_screens/options_screen_audio.cpp @@ -103,13 +103,21 @@ void OptionsScreenAudio::eventCallback(Widget* widget, const std::string& name, { if (name == "options_choice") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance()); - else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance()); - else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance()); - else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance()); - else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance()); + Screen *screen = NULL; + //if (selection == "tab_audio") + // screen = OptionsScreenAudio::getInstance(); + if (selection == "tab_video") + screen = OptionsScreenVideo::getInstance(); + else if (selection == "tab_players") + screen = TabbedUserScreen::getInstance(); + else if (selection == "tab_controls") + screen = OptionsScreenInput::getInstance(); + else if (selection == "tab_ui") + screen = OptionsScreenUI::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if(name == "back") { diff --git a/src/states_screens/options_screen_input.cpp b/src/states_screens/options_screen_input.cpp index 2570d2d38..41b6396dc 100644 --- a/src/states_screens/options_screen_input.cpp +++ b/src/states_screens/options_screen_input.cpp @@ -154,6 +154,15 @@ void OptionsScreenInput::init() const std::string name2("devices"); eventCallback(devices, name2, PLAYER_ID_GAME_MASTER); */ + // Disable adding keyboard configurations + if (StateManager::get()->getGameState() == GUIEngine::INGAME_MENU) + { + getWidget("add_device")->setDeactivated(); + } + else + { + getWidget("add_device")->setActivated(); + } } // init // ----------------------------------------------------------------------------- @@ -184,13 +193,21 @@ void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name, if (name == "options_choice") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance()); - else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance()); - else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance()); - else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance()); - else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance()); + Screen *screen = NULL; + if (selection == "tab_audio") + screen = OptionsScreenAudio::getInstance(); + else if (selection == "tab_video") + screen = OptionsScreenVideo::getInstance(); + else if (selection == "tab_players") + screen = TabbedUserScreen::getInstance(); + //else if (selection == "tab_controls") + // screen = OptionsScreenInput::getInstance(); + else if (selection == "tab_ui") + screen = OptionsScreenUI::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "add_device") { diff --git a/src/states_screens/options_screen_input2.cpp b/src/states_screens/options_screen_input2.cpp index 6e941a2ae..2f72ce1ed 100644 --- a/src/states_screens/options_screen_input2.cpp +++ b/src/states_screens/options_screen_input2.cpp @@ -61,6 +61,19 @@ void OptionsScreenInput2::loadedFromFile() // ---------------------------------------------------------------------------- +void OptionsScreenInput2::beforeAddingWidget() +{ + GUIEngine::ListWidget* w_list = + getWidget("actions"); + assert(w_list != NULL); + w_list->clearColumns(); + w_list->addColumn(_("Action"), 1); + w_list->addColumn(_("Key binding"), 1); + w_list->setSortable(false); +} + +// ---------------------------------------------------------------------------- + void OptionsScreenInput2::init() { Screen::init(); @@ -127,43 +140,72 @@ void OptionsScreenInput2::init() // their actualy contents will be adapted as needed after //I18N: Key binding section - actions->addItem("game_keys_section", _("Game Keys") ); - actions->addItem(KartActionStrings[PA_STEER_LEFT], L"" ); - actions->addItem(KartActionStrings[PA_STEER_RIGHT], L"" ); - actions->addItem(KartActionStrings[PA_ACCEL], L"" ); - actions->addItem(KartActionStrings[PA_BRAKE], L"" ); - actions->addItem(KartActionStrings[PA_FIRE], L"" ); - actions->addItem(KartActionStrings[PA_NITRO], L"" ); - actions->addItem(KartActionStrings[PA_DRIFT], L"" ); - actions->addItem(KartActionStrings[PA_LOOK_BACK], L"" ); - actions->addItem(KartActionStrings[PA_RESCUE], L"" ); - actions->addItem(KartActionStrings[PA_PAUSE_RACE], L"" ); + addListItemSubheader(actions, "game_keys_section", _("Game Keys")); + addListItem(actions, PA_STEER_LEFT); + addListItem(actions, PA_STEER_RIGHT); + addListItem(actions, PA_ACCEL); + addListItem(actions, PA_BRAKE); + addListItem(actions, PA_FIRE); + addListItem(actions, PA_NITRO); + addListItem(actions, PA_DRIFT); + addListItem(actions, PA_LOOK_BACK); + addListItem(actions, PA_RESCUE); + addListItem(actions, PA_PAUSE_RACE); //I18N: Key binding section - actions->addItem("menu_keys_section", _("Menu Keys") ); - actions->addItem(KartActionStrings[PA_MENU_UP], L"" ); - actions->addItem(KartActionStrings[PA_MENU_DOWN], L"" ); - actions->addItem(KartActionStrings[PA_MENU_LEFT], L"" ); - actions->addItem(KartActionStrings[PA_MENU_RIGHT], L"" ); - actions->addItem(KartActionStrings[PA_MENU_SELECT], L""); - actions->addItem(KartActionStrings[PA_MENU_CANCEL], L"" ); + addListItemSubheader(actions, "menu_keys_section", _("Menu Keys")); + addListItem(actions, PA_MENU_UP); + addListItem(actions, PA_MENU_DOWN); + addListItem(actions, PA_MENU_LEFT); + addListItem(actions, PA_MENU_RIGHT); + addListItem(actions, PA_MENU_SELECT); + addListItem(actions, PA_MENU_CANCEL); updateInputButtons(); + + // Disable deletion keyboard configurations + if (StateManager::get()->getGameState() == GUIEngine::INGAME_MENU) + { + getWidget("delete")->setDeactivated(); + } else + { + getWidget("delete")->setActivated(); + } } // init // ----------------------------------------------------------------------------- -irr::core::stringw OptionsScreenInput2::makeLabel( +void OptionsScreenInput2::addListItemSubheader(GUIEngine::ListWidget* actions, + const char* id, + const core::stringw& text) +{ + std::vector row; + row.push_back(GUIEngine::ListWidget::ListCell(text, -1, 1, false)); + row.push_back(GUIEngine::ListWidget::ListCell(L"", -1, 1, false)); + actions->addItem(id, row); +} + +// ----------------------------------------------------------------------------- + +void OptionsScreenInput2::addListItem(GUIEngine::ListWidget* actions, PlayerAction pa) +{ + std::vector row; + row.push_back(GUIEngine::ListWidget::ListCell(core::stringw(KartActionStrings[pa].c_str()), -1, 1, false)); + row.push_back(GUIEngine::ListWidget::ListCell(L"", -1, 1, false)); + actions->addItem(KartActionStrings[pa], row); +} + +// ----------------------------------------------------------------------------- + +void OptionsScreenInput2::renameRow(GUIEngine::ListWidget* actions, + int idRow, const irr::core::stringw &translatedName, PlayerAction action) const { - //hack: one tab character is supported by out font object, it moves the - // cursor to the middle of the area - core::stringw out = irr::core::stringw(" ") + translatedName + L"\t"; + actions->renameCell(idRow, 0, core::stringw(" ") + translatedName); + actions->renameCell(idRow, 1, m_config->getBindingAsString(action)); - out += m_config->getBindingAsString(action); - return out; } // makeLabel // ----------------------------------------------------------------------------- @@ -182,54 +224,54 @@ void OptionsScreenInput2::updateInputButtons() i++; // section header //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Steer Left"), PA_STEER_LEFT) ); + renameRow(actions, i++, _("Steer Left"), PA_STEER_LEFT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Steer Right"), PA_STEER_RIGHT) ); + renameRow(actions, i++, _("Steer Right"), PA_STEER_RIGHT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Accelerate"), PA_ACCEL) ); + renameRow(actions, i++, _("Accelerate"), PA_ACCEL); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Brake"), PA_BRAKE) ); + renameRow(actions, i++, _("Brake"), PA_BRAKE); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Fire"), PA_FIRE) ); + renameRow(actions, i++, _("Fire"), PA_FIRE); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Nitro"), PA_NITRO) ); + renameRow(actions, i++, _("Nitro"), PA_NITRO); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Skidding"), PA_DRIFT) ); + renameRow(actions, i++, _("Skidding"), PA_DRIFT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Look Back"), PA_LOOK_BACK) ); + renameRow(actions, i++, _("Look Back"), PA_LOOK_BACK); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Rescue"), PA_RESCUE) ); + renameRow(actions, i++, _("Rescue"), PA_RESCUE); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Pause Game"), PA_PAUSE_RACE) ); + renameRow(actions, i++, _("Pause Game"), PA_PAUSE_RACE); i++; // section header //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Up"), PA_MENU_UP) ); + renameRow(actions, i++, _("Up"), PA_MENU_UP); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Down"), PA_MENU_DOWN) ); + renameRow(actions, i++, _("Down"), PA_MENU_DOWN); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Left"), PA_MENU_LEFT) ); + renameRow(actions, i++, _("Left"), PA_MENU_LEFT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Right"), PA_MENU_RIGHT) ); + renameRow(actions, i++, _("Right"), PA_MENU_RIGHT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Select"), PA_MENU_SELECT) ); + renameRow(actions, i++, _("Select"), PA_MENU_SELECT); //I18N: Key binding name - actions->renameItem(i++, makeLabel( _("Cancel/Back"), PA_MENU_CANCEL) ); + renameRow(actions, i++, _("Cancel/Back"), PA_MENU_CANCEL); @@ -443,18 +485,21 @@ void OptionsScreenInput2::eventCallback(Widget* widget, StateManager *sm = StateManager::get(); if (name == "options_choice") { - const std::string &selection = - ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "tab_audio") - sm->replaceTopMostScreen(OptionsScreenAudio::getInstance()); - else if (selection == "tab_video") - sm->replaceTopMostScreen(OptionsScreenVideo::getInstance()); + Screen *screen = NULL; + if (selection == "tab_audio") + screen = OptionsScreenAudio::getInstance(); + //else if (selection == "tab_video") + // screen = OptionsScreenVideo::getInstance(); else if (selection == "tab_players") - sm->replaceTopMostScreen(TabbedUserScreen::getInstance()); + screen = TabbedUserScreen::getInstance(); + //else if (selection == "tab_controls") + // screen = OptionsScreenInput::getInstance(); else if (selection == "tab_ui") - sm->replaceTopMostScreen(OptionsScreenUI::getInstance()); - else if (selection == "tab_controls") {} + screen = OptionsScreenUI::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if (name == "back_to_device_list") { @@ -555,7 +600,8 @@ void OptionsScreenInput2::onConfirm() const bool success = input_manager->getDeviceList()->deleteConfig(m_config); assert(success); - if (!success) fprintf(stderr, "Failed to delete config!\n"); + if (!success) + Log::error("OptionsScreenInput2", "Failed to delete config!"); m_config = NULL; input_manager->getDeviceList()->serialize(); diff --git a/src/states_screens/options_screen_input2.hpp b/src/states_screens/options_screen_input2.hpp index 5bf3aeab1..1c273769f 100644 --- a/src/states_screens/options_screen_input2.hpp +++ b/src/states_screens/options_screen_input2.hpp @@ -25,7 +25,7 @@ #include "guiengine/screen.hpp" #include "states_screens/dialogs/message_dialog.hpp" -namespace GUIEngine { class Widget; } +namespace GUIEngine { class Widget; class ListWidget; } class DeviceConfig; namespace irr { namespace gui { class STKModifiedSpriteBank; } } @@ -50,8 +50,15 @@ class OptionsScreenInput2 : public GUIEngine::Screen, DeviceConfig* m_config; - irr::core::stringw makeLabel(const irr::core::stringw &translatedName, - PlayerAction action) const; + void renameRow(GUIEngine::ListWidget* actions, + int idRow, + const irr::core::stringw &translatedName, + PlayerAction action) const; + + void addListItem(GUIEngine::ListWidget* actions, PlayerAction pa); + void addListItemSubheader(GUIEngine::ListWidget* actions, + const char* id, + const core::stringw& text); public: friend class GUIEngine::ScreenSingleton; @@ -84,6 +91,8 @@ public: /** \brief Implement IConfirmDialogListener callback */ virtual void onConfirm() OVERRIDE; + + virtual void beforeAddingWidget() OVERRIDE; }; #endif diff --git a/src/states_screens/options_screen_ui.cpp b/src/states_screens/options_screen_ui.cpp index 73ba03208..23d370022 100644 --- a/src/states_screens/options_screen_ui.cpp +++ b/src/states_screens/options_screen_ui.cpp @@ -206,12 +206,21 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con { if (name == "options_choice") { - std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str(); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance()); - else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance()); - else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance()); - else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance()); + Screen *screen = NULL; + if (selection == "tab_audio") + screen = OptionsScreenAudio::getInstance(); + else if (selection == "tab_video") + screen = OptionsScreenVideo::getInstance(); + else if (selection == "tab_players") + screen = TabbedUserScreen::getInstance(); + else if (selection == "tab_controls") + screen = OptionsScreenInput::getInstance(); + //else if (selection == "tab_ui") + // screen = OptionsScreenUI::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else if(name == "back") { diff --git a/src/states_screens/options_screen_video.cpp b/src/states_screens/options_screen_video.cpp index 5c6a16a4c..c433c6a0c 100644 --- a/src/states_screens/options_screen_video.cpp +++ b/src/states_screens/options_screen_video.cpp @@ -167,15 +167,6 @@ void OptionsScreenVideo::init() if (UserConfigParams::m_fullscreen) rememberWinpos->setDeactivated(); else rememberWinpos->setActivated(); - // Enable back widgets if they were visited in-game previously - if (StateManager::get()->getGameState() != GUIEngine::INGAME_MENU) - { - res->setActivated(); - full->setActivated(); - applyBtn->setActivated(); - gfx->setActivated(); - getWidget("custom")->setActivated(); - } // --- get resolution list from irrlicht the first time if (!m_inited) @@ -342,6 +333,15 @@ void OptionsScreenVideo::init() gfx->setDeactivated(); getWidget("custom")->setDeactivated(); } + else + { + // Enable back widgets if they were visited in-game previously + res->setActivated(); + full->setActivated(); + applyBtn->setActivated(); + gfx->setActivated(); + getWidget("custom")->setActivated(); + } } // init // ---------------------------------------------------------------------------- @@ -469,15 +469,13 @@ void OptionsScreenVideo::eventCallback(Widget* widget, const std::string& name, { if (name == "options_choice") { - std::string selection = - ((RibbonWidget*)widget) - ->getSelectionIDString(PLAYER_ID_GAME_MASTER); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); Screen *screen = NULL; if (selection == "tab_audio") screen = OptionsScreenAudio::getInstance(); - else if (selection == "tab_video") - screen = OptionsScreenVideo::getInstance(); + //else if (selection == "tab_video") + // screen = OptionsScreenVideo::getInstance(); else if (selection == "tab_players") screen = TabbedUserScreen::getInstance(); else if (selection == "tab_controls") diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index 38b43a193..40c4474ee 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -63,9 +63,9 @@ RaceGUI::RaceGUI() // Originally m_map_height was 100, and we take 480 as minimum res const float scaling = irr_driver->getFrameSize().Height / 480.0f; // Marker texture has to be power-of-two for (old) OpenGL compliance - m_marker_rendered_size = 2 << ((int) ceil(1.0 + log(32.0 * scaling))); - m_marker_ai_size = (int)( 14.0f * scaling); - m_marker_player_size = (int)( 16.0f * scaling); + //m_marker_rendered_size = 2 << ((int) ceil(1.0 + log(32.0 * scaling))); + m_minimap_ai_size = (int)( 14.0f * scaling); + m_minimap_player_size = (int)( 16.0f * scaling); m_map_width = (int)(100.0f * scaling); m_map_height = (int)(100.0f * scaling); m_map_left = (int)( 10.0f * scaling); @@ -87,7 +87,7 @@ RaceGUI::RaceGUI() m_speed_meter_icon = material_manager->getMaterial("speedback.png"); m_speed_bar_icon = material_manager->getMaterial("speedfore.png"); - createMarkerTexture(); + //createMarkerTexture(); // Determine maximum length of the rank/lap text, in order to // align those texts properly on the right side of the viewport. @@ -108,7 +108,7 @@ RaceGUI::RaceGUI() int n = race_manager->getNumberOfKarts(); m_animation_states.resize(n); - m_rank_animation_start_times.resize(n); + m_rank_animation_duration.resize(n); m_last_ranks.resize(n); } // RaceGUI @@ -211,7 +211,7 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt) if(!World::getWorld()->isRacePhase()) return; drawPowerupIcons (kart, viewport, scaling); - drawSpeedEnergyRank(kart, viewport, scaling); + drawSpeedEnergyRank(kart, viewport, scaling, dt); if (!m_is_tutorial) drawLap(kart, viewport, scaling); @@ -238,15 +238,17 @@ void RaceGUI::drawScores() irr::video::ITexture *team_icon; int numLeader = 1; - for(unsigned int i=0; igetNumKarts(); i++){ + for(unsigned int i=0; igetNumKarts(); i++) + { int j = soccerWorld->getTeamLeader(i); if(j < 0) break; - core::rect source(j*m_marker_rendered_size, 0, - (j+1)*m_marker_rendered_size,m_marker_rendered_size); + AbstractKart* kart = soccerWorld->getKart(i); + video::ITexture* icon = kart->getKartProperties()->getMinimapIcon(); + core::rect source(core::position2di(0, 0), icon->getSize()); core::recti position(offsetX, offsetY, - offsetX + 2*m_marker_player_size, offsetY + 2*m_marker_player_size); - draw2DImage(m_marker, position, source, + offsetX + 2*m_minimap_player_size, offsetY + 2*m_minimap_player_size); + draw2DImage(icon, position, source, NULL, NULL, true); core::stringw score = StringUtils::toWString(soccerWorld->getScore(i)); int string_height = @@ -265,8 +267,8 @@ void RaceGUI::drawScores() default: break; } core::rect indicatorPos(offsetX, offsetY, - offsetX + (int)(m_marker_player_size/1.25f), - offsetY + (int)(m_marker_player_size/1.25f)); + offsetX + (int)(m_minimap_player_size/1.25f), + offsetY + (int)(m_minimap_player_size/1.25f)); core::rect sourceRect(core::position2d(0,0), team_icon->getOriginalSize()); draw2DImage(team_icon,indicatorPos,sourceRect, @@ -373,20 +375,19 @@ void RaceGUI::drawGlobalMiniMap() const Vec3& xyz = kart->getXYZ(); Vec3 draw_at; world->getTrack()->mapPoint2MiniMap(xyz, &draw_at); + + video::ITexture* icon = kart->getKartProperties()->getMinimapIcon(); + // int marker_height = m_marker->getOriginalSize().Height; - core::rect source(i *m_marker_rendered_size, - 0, - (i+1)*m_marker_rendered_size, - m_marker_rendered_size); + core::rect source(core::position2di(0, 0), icon->getSize()); int marker_half_size = (kart->getController()->isPlayerController() - ? m_marker_player_size - : m_marker_ai_size )>>1; + ? m_minimap_player_size + : m_minimap_ai_size )>>1; core::rect position(m_map_left+(int)(draw_at.getX()-marker_half_size), lower_y -(int)(draw_at.getY()+marker_half_size), m_map_left+(int)(draw_at.getX()+marker_half_size), lower_y -(int)(draw_at.getY()-marker_half_size)); - draw2DImage(m_marker, position, source, - NULL, NULL, true); + draw2DImage(icon, position, source, NULL, NULL, true); } // for i(World::getWorld()); @@ -616,10 +625,14 @@ void RaceGUI::drawRank(const AbstractKart *kart, { if (m_last_ranks[id] != kart->getPosition()) { - m_rank_animation_start_times[id] = world->getTime(); + m_rank_animation_duration[id] = 0.0f; m_animation_states[id] = AS_SMALLER; } } + else + { + m_rank_animation_duration[id] += dt; + } float scale = 1.0f; int rank = kart->getPosition(); @@ -627,13 +640,12 @@ void RaceGUI::drawRank(const AbstractKart *kart, const float MIN_SHRINK = 0.3f; if (m_animation_states[id] == AS_SMALLER) { - scale = 1.0f - (world->getTime() - m_rank_animation_start_times[id]) - / DURATION; + scale = 1.0f - m_rank_animation_duration[id]/ DURATION; rank = m_last_ranks[id]; if (scale < MIN_SHRINK) { m_animation_states[id] = AS_BIGGER; - m_rank_animation_start_times[id] = world->getTime(); + m_rank_animation_duration[id] = 0.0f; // Store the new rank m_last_ranks[id] = kart->getPosition(); scale = MIN_SHRINK; @@ -641,8 +653,7 @@ void RaceGUI::drawRank(const AbstractKart *kart, } else if (m_animation_states[id] == AS_BIGGER) { - scale = (world->getTime() - m_rank_animation_start_times[id]) - / DURATION + MIN_SHRINK; + scale = m_rank_animation_duration[id] / DURATION + MIN_SHRINK; rank = m_last_ranks[id]; if (scale > 1.0f) { @@ -679,10 +690,12 @@ void RaceGUI::drawRank(const AbstractKart *kart, * \param kart The kart for which to show the data. * \param viewport The viewport to use. * \param scaling Which scaling to apply to the speedometer. + * \param dt Time step size. */ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart, const core::recti &viewport, - const core::vector2df &scaling) + const core::vector2df &scaling, + float dt) { float min_ratio = std::min(scaling.X, scaling.Y); const int SPEEDWIDTH = 128; @@ -711,7 +724,7 @@ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart, const float speed = kart->getSpeed(); - drawRank(kart, offset, min_ratio, meter_width, meter_height); + drawRank(kart, offset, min_ratio, meter_width, meter_height, dt); if(speed <=0) return; // Nothing to do if speed is negative. diff --git a/src/states_screens/race_gui.hpp b/src/states_screens/race_gui.hpp index c96343409..8ae4d626b 100644 --- a/src/states_screens/race_gui.hpp +++ b/src/states_screens/race_gui.hpp @@ -51,11 +51,11 @@ private: /** The size of a single marker on the screen for AI karts, * need not be a power of 2. */ - int m_marker_ai_size; + int m_minimap_ai_size; /** The size of a single marker on the screen or player karts, * need not be a power of 2. */ - int m_marker_player_size; + int m_minimap_player_size; /** The width of the rendered mini map in pixels, must be a power of 2. */ int m_map_rendered_width; @@ -89,8 +89,8 @@ private: enum AnimationState {AS_NONE, AS_SMALLER, AS_BIGGER}; std::vector m_animation_states; - /** When the animation state was changed. */ - std::vector m_rank_animation_start_times; + /** How long the rank animation has been shown. */ + std::vector m_rank_animation_duration; /** Stores the previous rank for each kart. Used for the rank animation. */ std::vector m_last_ranks; @@ -103,14 +103,14 @@ private: const core::vector2df &scaling); void drawSpeedEnergyRank (const AbstractKart* kart, const core::recti &viewport, - const core::vector2df &scaling); + const core::vector2df &scaling, float dt); void drawLap (const AbstractKart* kart, const core::recti &viewport, const core::vector2df &scaling); void drawRank (const AbstractKart *kart, const core::vector2df &offset, float min_ratio, int meter_width, - int meter_height); + int meter_height, float dt); /** Display items that are shown once only (for all karts). */ void drawGlobalMiniMap (); diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp index bcb2f83eb..a25e94ee2 100644 --- a/src/states_screens/race_gui_base.cpp +++ b/src/states_screens/race_gui_base.cpp @@ -151,101 +151,13 @@ void RaceGUIBase::reset() */ RaceGUIBase::~RaceGUIBase() { - irr_driver->removeTexture(m_marker); + //irr_driver->removeTexture(m_marker); // If the referee is currently being shown, // remove it from the scene graph. delete m_referee; } // ~RaceGUIBase -//----------------------------------------------------------------------------- -/** Creates a texture with the markers for all karts in the current race - * on it. This assumes that nothing is attached to the scene node at - * this stage. - */ -void RaceGUIBase::createMarkerTexture() -{ - unsigned int num_karts = race_manager->getNumberOfKarts(); - unsigned int npower2 = 1; - // Textures must be power of 2, so - while(npower2>1)-1; - IrrDriver::RTTProvider rttProvider(core::dimension2du(m_marker_rendered_size - *npower2, - m_marker_rendered_size), - "RaceGUI::markers", true); - scene::ICameraSceneNode *camera = irr_driver->addCameraSceneNode(); - core::matrix4 projection; - projection.buildProjectionMatrixOrthoLH((float)(m_marker_rendered_size*npower2), - (float)(m_marker_rendered_size), - -1.0f, 1.0f); - camera->setProjectionMatrix(projection, true); - core::vector3df center( (float)(m_marker_rendered_size*npower2>>1), - (float)(m_marker_rendered_size>>1), 0.0f); - camera->setPosition(center); - camera->setUpVector(core::vector3df(0,1,0)); - camera->setTarget(center + core::vector3df(0,0,4)); - // The call to render sets the projection matrix etc. So we have to call - // this now before doing the direct OpenGL calls. - // FIXME: perhaps we should use three calls to irr_driver: begin(), - // render(), end() - so we could do the rendering by calling to - // draw2DPolygon() between render() and end(), avoiding the - // call to camera->render() - camera->render(); - // We have to reset the material here, since otherwise the last - // set material (i.e from the kart selection screen) will be used - // when rednering to the texture. - video::SMaterial m; - m.setTexture(0, NULL); - irr_driver->getVideoDriver()->setMaterial(m); - for(unsigned int i=0; igetKartIdent(i); - assert(kart_ident.size() > 0); - - const KartProperties *kp=kart_properties_manager->getKart(kart_ident); - assert(kp != NULL); - - core::vector2df center((float)((m_marker_rendered_size>>1) - +i*m_marker_rendered_size), - (float)(m_marker_rendered_size>>1) ); - int count = kp->getShape(); - video::ITexture *t = kp->getMinimapIcon(); - if(t) - { - video::ITexture *t = kp->getIconMaterial()->getTexture(); - core::recti dest_rect(i*m_marker_rendered_size, - 0, - (i+1)*m_marker_rendered_size, - m_marker_rendered_size); - core::recti source_rect(core::vector2di(0,0), t->getSize()); - draw2DImage(t, dest_rect, - source_rect, - /*clipRect*/0, - /*color*/ 0, - /*useAlpha*/true); - } - else // no special minimap icon defined - { - video::S3DVertex *vertices = new video::S3DVertex[count+1]; - unsigned short int *index = new unsigned short int[count+1]; - video::SColor color = kp->getColor(); - createRegularPolygon(count, (float)radius, center, color, - vertices, index); - irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, - count, index, count-2, - video::EVT_STANDARD, - scene::EPT_TRIANGLE_FAN); - delete [] vertices; - delete [] index; - } // if special minimap icon defined - } - - m_marker = rttProvider.renderToTexture(-1, /*is_2d_render*/true); - irr_driver->removeCameraSceneNode(camera); -} // createMarkerTexture - //----------------------------------------------------------------------------- /** Creates the 2D vertices for a regular polygon. Adopted from Irrlicht. * \param n Number of vertices to use. diff --git a/src/states_screens/race_gui_base.hpp b/src/states_screens/race_gui_base.hpp index 55bce3039..05a20beb7 100644 --- a/src/states_screens/race_gui_base.hpp +++ b/src/states_screens/race_gui_base.hpp @@ -170,10 +170,10 @@ protected: core::vector2df m_plunger_speed; /** The size of a single marker in pixels, must be a power of 2. */ - int m_marker_rendered_size; + //int m_marker_rendered_size; /** A texture with all mini dots to be displayed in the minimap for all karts. */ - video::ITexture *m_marker; + //video::ITexture *m_marker; video::ITexture *m_gauge_empty; /** Default texture for nitro gauge. */ video::ITexture *m_gauge_full; @@ -186,7 +186,7 @@ protected: Material *m_icons_frame; void cleanupMessages(const float dt); - void createMarkerTexture(); + //void createMarkerTexture(); void createRegularPolygon(unsigned int n, float radius, const core::vector2df ¢er, const video::SColor &color, diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp index a2a7299f8..cdef71b1e 100644 --- a/src/states_screens/race_gui_overworld.cpp +++ b/src/states_screens/race_gui_overworld.cpp @@ -77,11 +77,11 @@ RaceGUIOverworld::RaceGUIOverworld() const float scaling = irr_driver->getFrameSize().Height / 420.0f; // Marker texture has to be power-of-two for (old) OpenGL compliance - m_marker_rendered_size = 2 << ((int) ceil(1.0 + log(32.0 * scaling))); - m_marker_challenge_size = (int)( 12.0f * scaling); - m_marker_player_size = (int)( 24.0f * scaling); - m_map_width = (int)(250.0f * scaling); - m_map_height = (int)(250.0f * scaling); + //m_marker_rendered_size = 2 << ((int) ceil(1.0 + log(32.0 * scaling))); + m_minimap_challenge_size = (int)( 12.0f * scaling); + m_minimap_player_size = (int)( 24.0f * scaling); + m_map_width = (int)(250.0f * scaling); + m_map_height = (int)(250.0f * scaling); m_map_left = 20; m_map_bottom = UserConfigParams::m_height-10; @@ -100,7 +100,7 @@ RaceGUIOverworld::RaceGUIOverworld() m_speed_meter_icon = material_manager->getMaterial("speedback.png"); m_speed_bar_icon = material_manager->getMaterial("speedfore.png"); - createMarkerTexture(); + //createMarkerTexture(); // Translate strings only one in constructor to avoid calling // gettext in each frame. @@ -363,13 +363,11 @@ void RaceGUIOverworld::drawGlobalMiniMap() Vec3 draw_at; track->mapPoint2MiniMap(kart_xyz, &draw_at); - core::rect source(i *m_marker_rendered_size, - 0, - (i+1)*m_marker_rendered_size, - m_marker_rendered_size); + video::ITexture* icon = kart->getKartProperties()->getMinimapIcon(); + core::rect source(core::position2di(0, 0), icon->getSize()); int marker_half_size = (kart->getController()->isPlayerController() - ? m_marker_player_size - : m_marker_challenge_size )>>1; + ? m_minimap_player_size + : m_minimap_challenge_size )>>1; core::rect position(m_map_left+(int)(draw_at.getX()-marker_half_size), lower_y -(int)(draw_at.getY()+marker_half_size), m_map_left+(int)(draw_at.getX()+marker_half_size), @@ -390,8 +388,7 @@ void RaceGUIOverworld::drawGlobalMiniMap() rect, NULL, colors, true); } // if isPlayerController - draw2DImage(m_marker, position, source, - NULL, NULL, true); + draw2DImage(icon, position, source, NULL, NULL, true); } // for i source(core::position2d(0,0), m_icons[state]->getOriginalSize()); - int marker_size = m_marker_challenge_size; + int marker_size = m_minimap_challenge_size; core::position2di mouse = irr_driver->getMouseLocation(); core::rect dest(m_map_left+(int)(draw_at.getX()-marker_size/2), lower_y -(int)(draw_at.getY()+marker_size/2), @@ -474,8 +471,8 @@ void RaceGUIOverworld::drawGlobalMiniMap() if (challenge == NULL) { - fprintf(stderr, "[RaceGUIOverworld] ERROR: Cannot find challenge <%s>\n", - challenges[n].m_challenge_id.c_str()); + Log::error("RaceGUIOverworld", "Cannot find challenge <%s>.", + challenges[n].m_challenge_id.c_str()); break; } @@ -486,10 +483,10 @@ void RaceGUIOverworld::drawGlobalMiniMap() if (gp == NULL) { - fprintf(stderr, "[RaceGUIOverworld] ERROR: Cannot find GP <%s>, " - "referenced from challenge <%s>\n", - challenge->getGPId().c_str(), - challenges[n].m_challenge_id.c_str()); + Log::error("RaceGUIOverworld", "Cannot find GP <%s>, " + "referenced from challenge <%s>", + challenge->getGPId().c_str(), + challenges[n].m_challenge_id.c_str()); break; } @@ -511,10 +508,10 @@ void RaceGUIOverworld::drawGlobalMiniMap() Track* track = track_manager->getTrack(challenge->getTrackId()); if (track == NULL) { - fprintf(stderr, "[RaceGUIOverworld] ERROR: Cannot find track <%s>, " - "referenced from challenge <%s>\n", - challenge->getTrackId().c_str(), - challenges[n].m_challenge_id.c_str()); + Log::error("RaceGUIOverworld", "Cannot find track <%s>, " + "referenced from challenge <%s>", + challenge->getTrackId().c_str(), + challenges[n].m_challenge_id.c_str()); break; } diff --git a/src/states_screens/race_gui_overworld.hpp b/src/states_screens/race_gui_overworld.hpp index beed1b9c2..950c2d9bd 100644 --- a/src/states_screens/race_gui_overworld.hpp +++ b/src/states_screens/race_gui_overworld.hpp @@ -75,11 +75,11 @@ private: /** The size of a single marker on the screen for AI karts, * need not be a power of 2. */ - int m_marker_challenge_size; + int m_minimap_challenge_size; /** The size of a single marker on the screen or player karts, * need not be a power of 2. */ - int m_marker_player_size; + int m_minimap_player_size; /** The width of the rendered mini map in pixels, must be a power of 2. */ int m_map_rendered_width; diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 9b5803421..73c7b3577 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -297,9 +297,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, } return; } - fprintf(stderr, "Incorrect event '%s' when things are unlocked.\n", - name.c_str()); - assert(false); + Log::fatal("RaceResultGUI", "Incorrect event '%s' when things are unlocked.", + name.c_str()); } // If we're playing online : @@ -342,11 +341,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, MessageDialog::MESSAGE_DIALOG_CONFIRM, this, false); } else if (!getWidget(name.c_str())->isVisible()) - { - fprintf(stderr, "Incorrect event '%s' when things are unlocked.\n", - name.c_str()); - assert(false); - } + Log::fatal("RaceResultGUI", "Incorrect event '%s' when things are unlocked.", + name.c_str()); return; } @@ -387,10 +383,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, } } else - { - fprintf(stderr, "Incorrect event '%s' for normal race.\n", - name.c_str()); - } + Log::fatal("RaceResultGUI", "Incorrect event '%s' for normal race.", + name.c_str()); return; } // eventCallback @@ -615,8 +609,8 @@ void RaceResultGUI::onUpdate(float dt) } catch (std::exception& e) { - fprintf(stderr, "[RaceResultGUI] WARNING: exception caught when " - "trying to load music: %s\n", e.what()); + Log::error("RaceResultGUI", "Exception caught when " + "trying to load music: %s", e.what()); } } } // onUpdate diff --git a/src/states_screens/user_screen.cpp b/src/states_screens/user_screen.cpp index de5b1fa72..64b93630c 100644 --- a/src/states_screens/user_screen.cpp +++ b/src/states_screens/user_screen.cpp @@ -108,6 +108,21 @@ void BaseUserScreen::init() else if (PlayerManager::get()->getNumPlayers() > 0) selectUser(0); + // Disable changing the user while in game + if (StateManager::get()->getGameState() == GUIEngine::INGAME_MENU) + { + getWidget("ok")->setDeactivated(); + getWidget("new_user")->setDeactivated(); + getWidget("rename")->setDeactivated(); + getWidget("delete")->setDeactivated(); + } + else + { + getWidget("ok")->setActivated(); + getWidget("new_user")->setActivated(); + getWidget("rename")->setActivated(); + getWidget("delete")->setActivated(); + } } // init // ---------------------------------------------------------------------------- @@ -572,16 +587,21 @@ void TabbedUserScreen::eventCallback(GUIEngine::Widget* widget, { if (name == "options_choice") { - const std::string &selection = - ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); - Screen *s; - if (selection=="tab_audio" ) s = OptionsScreenAudio::getInstance(); - else if (selection=="tab_video" ) s = OptionsScreenVideo::getInstance(); - else if (selection=="tab_players" ) s = TabbedUserScreen::getInstance(); - else if (selection=="tab_controls") s = OptionsScreenInput::getInstance(); - else if (selection=="tab_ui" ) s = OptionsScreenUI::getInstance(); - assert(s); - StateManager::get()->replaceTopMostScreen(s); + std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER); + + Screen *screen = NULL; + if (selection == "tab_audio") + screen = OptionsScreenAudio::getInstance(); + else if (selection == "tab_video") + screen = OptionsScreenVideo::getInstance(); + //else if (selection == "tab_players") + // screen = TabbedUserScreen::getInstance(); + else if (selection == "tab_controls") + screen = OptionsScreenInput::getInstance(); + else if (selection == "tab_ui") + screen = OptionsScreenUI::getInstance(); + if(screen) + StateManager::get()->replaceTopMostScreen(screen); } else BaseUserScreen::eventCallback(widget, name, player_id); diff --git a/src/tracks/check_cannon.cpp b/src/tracks/check_cannon.cpp index 4b0120e6b..7effbe71b 100644 --- a/src/tracks/check_cannon.cpp +++ b/src/tracks/check_cannon.cpp @@ -36,12 +36,8 @@ CheckCannon::CheckCannon(const XMLNode &node, unsigned int index) : CheckLine(node, index) { core::vector3df p1, p2; - if(!node.get("target-p1", &p1) || - !node.get("target-p2", &p2) ) - { - printf("CheckCannon has no target line specified.\n"); - exit(-1); - } + if(!node.get("target-p1", &p1) || !node.get("target-p2", &p2)) + Log::fatal("CheckCannon", "No target line specified."); m_target.setLine(p1, p2); m_curve = new Ipo(*(node.getNode("curve")), /*fps*/25, diff --git a/src/tracks/check_goal.cpp b/src/tracks/check_goal.cpp index 736859cbf..f582f182f 100644 --- a/src/tracks/check_goal.cpp +++ b/src/tracks/check_goal.cpp @@ -72,8 +72,8 @@ void CheckGoal::update(float dt) if(isTriggered(m_previous_position[ball_index], xyz, ball_index)) { if(UserConfigParams::m_check_debug) - printf("CHECK: Goal check structure %d triggered for object %s.\n", - m_index, obj->getPresentation()->getNode()->getDebugName()); + Log::info("CheckGoal", "Goal check structure %d triggered for object %s.", + m_index, obj->getPresentation()->getNode()->getDebugName()); trigger(ball_index); } m_previous_position[ball_index] = xyz; diff --git a/src/tracks/check_lap.cpp b/src/tracks/check_lap.cpp index 71f6591af..bf92b9b10 100644 --- a/src/tracks/check_lap.cpp +++ b/src/tracks/check_lap.cpp @@ -71,11 +71,10 @@ bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, bool result =(m_previous_distance[indx]>0.95f*track_length && current_distance<7.0f); if(UserConfigParams::m_check_debug && result) - { - printf("CHECK: Kart %s crossed start line from %f to %f.\n", - World::getWorld()->getKart(indx)->getIdent().c_str(), - m_previous_distance[indx], current_distance); - } + Log::info("CheckLap", "Kart %s crossed start line from %f to %f.", + World::getWorld()->getKart(indx)->getIdent().c_str(), + m_previous_distance[indx], current_distance); + m_previous_distance[indx] = current_distance; return result; diff --git a/src/tracks/check_line.cpp b/src/tracks/check_line.cpp index 36015b334..f67c76b29 100644 --- a/src/tracks/check_line.cpp +++ b/src/tracks/check_line.cpp @@ -173,14 +173,14 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, if(UserConfigParams::m_check_debug && !result) { if(World::getWorld()->getNumKarts()>0) - printf("CHECK: Kart %s crosses line, but wrong height " - "(%f vs %f).\n", - World::getWorld()->getKart(indx)->getIdent().c_str(), - new_pos.getY(), m_min_height); + Log::info("CheckLine", "Kart %s crosses line, but wrong height " + "(%f vs %f).", + World::getWorld()->getKart(indx)->getIdent().c_str(), + new_pos.getY(), m_min_height); else - printf("CHECK: Kart %d crosses line, but wrong height " - "(%f vs %f).\n", - indx, new_pos.getY(), m_min_height); + Log::info("CheckLine", "Kart %d crosses line, but wrong height " + "(%f vs %f).", + indx, new_pos.getY(), m_min_height); } } diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index f80b6be39..7ece0621e 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -64,7 +64,7 @@ void CheckManager::load(const XMLNode &node) m_all_checks.push_back(cs); } // checksphere else - printf("Unknown check structure '%s' - ignored.\n", type.c_str()); + Log::warn("CheckManager", "Unknown check structure '%s' - ignored.", type.c_str()); } // for i(c) != NULL) return i; } - fprintf(stderr, - "No check-lap structure found! This can cause incorrect kart\n"); - fprintf(stderr, - "ranking when crossing the line, but can otherwise be ignored.\n"); + Log::warn("CheckManager", "No check-lap structure found! This can cause incorrect kart"); + Log::warn("CheckManager", "ranking when crossing the line, but can otherwise be ignored."); for (unsigned int i=0; igetType()==CheckStructure::CT_NEW_LAP) return i; } - fprintf(stderr, "Error, no kind of lap line for track found, aborting.\n"); - exit(-1); + Log::fatal("CheckManager", "Error, no kind of lap line for track found, aborting."); } // getLapLineIndex // ---------------------------------------------------------------------------- diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index 5a3f8b05e..a99b19ca9 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -54,9 +54,7 @@ CheckStructure::CheckStructure(const XMLNode &node, unsigned int index) else if(node.getName()=="cannon") m_check_type = CT_CANNON; else - { - printf("Unknown check structure '%s' - ignored.\n", kind.c_str()); - } + Log::warn("CheckStructure", "Unknown check structure '%s' - ignored.", kind.c_str()); node.get("same-group", &m_same_group); // Make sure that the index of this check structure is included in @@ -108,8 +106,8 @@ void CheckStructure::update(float dt) if(m_is_active[i] && isTriggered(m_previous_position[i], xyz, i)) { if(UserConfigParams::m_check_debug) - printf("CHECK: Check structure %d triggered for kart %s.\n", - m_index, world->getKart(i)->getIdent().c_str()); + Log::info("CheckStructure", "Check structure %d triggered for kart %s.", + m_index, world->getKart(i)->getIdent().c_str()); trigger(i); } m_previous_position[i] = xyz; @@ -144,18 +142,18 @@ void CheckStructure::changeStatus(const std::vector indices, cs->m_is_active[kart_index] = false; if(UserConfigParams::m_check_debug) { - printf("CHECK: Deactivating %d for %s.\n", - indices[i], - World::getWorld()->getKart(kart_index)->getIdent().c_str()); + Log::info("CheckStructure", "Deactivating %d for %s.", + indices[i], + World::getWorld()->getKart(kart_index)->getIdent().c_str()); } break; case CS_ACTIVATE: cs->m_is_active[kart_index] = true; if(UserConfigParams::m_check_debug) { - printf("CHECK: Activating %d for %s.\n", - indices[i], - World::getWorld()->getKart(kart_index)->getIdent().c_str()); + Log::info("CheckStructure", "Activating %d for %s.", + indices[i], + World::getWorld()->getKart(kart_index)->getIdent().c_str()); } break; case CS_TOGGLE: @@ -166,10 +164,10 @@ void CheckStructure::changeStatus(const std::vector indices, // non-POD type 'struct std::_Bit_reference' through '...'; // call will abort at runtime"). So we use this somewhat // unusual but portable construct. - printf("CHECK: Toggling %d for %s from %d.\n", - indices[i], - World::getWorld()->getKart(kart_index)->getIdent().c_str(), - cs->m_is_active[kart_index]==true); + Log::info("CheckStructure", "Toggling %d for %s from %d.", + indices[i], + World::getWorld()->getKart(kart_index)->getIdent().c_str(), + cs->m_is_active[kart_index]==true); } cs->m_is_active[kart_index] = !cs->m_is_active[kart_index]; } // switch @@ -213,9 +211,9 @@ void CheckStructure::trigger(unsigned int kart_index) World::getWorld()->newLap(kart_index); if(UserConfigParams::m_check_debug) { - printf("CHECK: %s new lap %d triggered\n", - World::getWorld()->getKart(kart_index)->getIdent().c_str(), - m_index); + Log::info("CheckStructure", "%s new lap %d triggered", + World::getWorld()->getKart(kart_index)->getIdent().c_str(), + m_index); } changeStatus(m_check_structures_to_change_state, kart_index, CS_ACTIVATE); diff --git a/src/tracks/graph_node.cpp b/src/tracks/graph_node.cpp index 4803f6f14..ae7b27578 100644 --- a/src/tracks/graph_node.cpp +++ b/src/tracks/graph_node.cpp @@ -31,10 +31,8 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index) { if (quad_index >= QuadSet::get()->getNumberOfQuads()) - { - fprintf(stderr, "[GraphNode] ERROR: No driveline found, or empty driveline"); - abort(); - } + Log::fatal("GraphNode", "No driveline found, or empty driveline."); + m_quad_index = quad_index; m_node_index = node_index; m_distance_from_start = -1.0f; @@ -138,10 +136,10 @@ void GraphNode::setupPathsToNode() gn.markAllSuccessorsToUse(i, &m_path_to_node); } #ifdef DEBUG - for(unsigned int i=0; igetNode(next_node.getSuccessor(fork_number%next_node.getNumberOfSuccessors())); addUnrolledQuad(next, fork_number, k); -} \ No newline at end of file +} diff --git a/src/tracks/quad.cpp b/src/tracks/quad.cpp index eff177e05..6f74a0662 100644 --- a/src/tracks/quad.cpp +++ b/src/tracks/quad.cpp @@ -17,6 +17,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "tracks/quad.hpp" +#include "utils/log.hpp" #include #include @@ -35,10 +36,10 @@ Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3, if(p1.sideOfLine2D(p0, p2)>0 || p3.sideOfLine2D(p0, p2)<0) { - printf("Warning: quad has wrong orientation: p0=%f %f %f p1=%f %f %f\n", - p0.getX(), p0.getY(), p0.getZ(),p1.getX(), p1.getY(), p1.getZ()); - printf("The quad will be swapped, nevertheless test for correctness -\n"); - printf("quads must be counter-clockwise oriented.\n"); + Log::warn("Quad", "Quad has wrong orientation: p0=%f %f %f p1=%f %f %f", + p0.getX(), p0.getY(), p0.getZ(),p1.getX(), p1.getY(), p1.getZ()); + Log::warn("Quad", "The quad will be swapped, nevertheless test for correctness -"); + Log::warn("Quad", "quads must be counter-clockwise oriented."); m_p[0]=p1; m_p[1]=p0; m_p[2]=p3; m_p[3]=p2; } else diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 20cbfae32..52a938683 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -377,7 +377,6 @@ void Track::cleanup() irr_driver->clearGlowingNodes(); irr_driver->clearLights(); irr_driver->clearForcedBloom(); - irr_driver->clearDisplacingNodes(); irr_driver->clearBackgroundNodes(); if(UserConfigParams::logMemory()) diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 1d7073569..6b715dac9 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -498,10 +498,7 @@ public: btTransform getStartTransform (unsigned int index) const { if (index >= m_start_transforms.size()) - { - fprintf(stderr, "No start position for kart %i\n", index); - abort(); - } + Log::fatal("Tracj", "No start position for kart %i.", index); return m_start_transforms[index]; } // ------------------------------------------------------------------------ diff --git a/src/tracks/track_manager.cpp b/src/tracks/track_manager.cpp index c987ec522..b2092b13e 100644 --- a/src/tracks/track_manager.cpp +++ b/src/tracks/track_manager.cpp @@ -98,9 +98,8 @@ void TrackManager::setUnavailableTracks(const std::vector &tracks) if (std::find(tracks.begin(), tracks.end(), id)==tracks.end()) { m_track_avail[i-m_tracks.begin()] = false; - fprintf(stderr, - "Track '%s' not available on all clients, disabled.\n", - id.c_str()); + Log::warn("TrackManager", "Track '%s' not available on all clients, disabled.", + id.c_str()); } // if id not in tracks } // for all available tracks in track manager @@ -174,7 +173,7 @@ bool TrackManager::loadTrack(const std::string& dirname) } catch (std::exception& e) { - fprintf(stderr, "[TrackManager] ERROR: Cannot load track <%s> : %s\n", + Log::error("TrackManager", "Cannot load track <%s> : %s\n", dirname.c_str(), e.what()); return false; } @@ -182,12 +181,12 @@ bool TrackManager::loadTrack(const std::string& dirname) if (track->getVersion()m_min_track_version || track->getVersion()>stk_config->m_max_track_version) { - fprintf(stderr, "[TrackManager] Warning: track '%s' is not supported " + Log::warn("TrackManager", "Track '%s' is not supported " "by this binary, ignored. (Track is version %i, this " - "executable supports from %i to %i)\n", - track->getIdent().c_str(), track->getVersion(), - stk_config->m_min_track_version, - stk_config->m_max_track_version); + "executable supports from %i to %i).", + track->getIdent().c_str(), track->getVersion(), + stk_config->m_min_track_version, + stk_config->m_max_track_version); delete track; return false; } @@ -206,22 +205,15 @@ void TrackManager::removeTrack(const std::string &ident) { Track *track = getTrack(ident); if (track == NULL) - { - fprintf(stderr, "[TrackManager] ERROR: There is no track named '%s'!!\n", ident.c_str()); - assert(false); - return; - } + Log::fatal("TrackManager", "There is no track named '%s'!!", ident.c_str()); if (track->isInternal()) return; std::vector::iterator it = std::find(m_tracks.begin(), m_tracks.end(), track); if (it == m_tracks.end()) - { - fprintf(stderr, "[TrackManager] INTERNAL ERROR: Cannot find track '%s' in map!!\n", ident.c_str()); - assert(false); - return; - } + Log::fatal("TrackManager", "Cannot find track '%s' in map!!", ident.c_str()); + int index = it - m_tracks.begin(); // Remove the track from all groups it belongs to diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 9cb251f29..f7cefd16e 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -215,14 +215,6 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, irr_driver->addForcedBloomNode(glownode, power); } - - bool displacing = false; - if (xml_node.get("displacing", &displacing) && displacing && glownode) - { - irr_driver->addDisplacingNode(glownode); - glownode->setVisible(false); - glownode->updateAbsolutePosition(); - } } diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index 732e57224..6aef4dcc7 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -27,6 +27,7 @@ #include "graphics/mesh_tools.hpp" #include "graphics/particle_emitter.hpp" #include "graphics/particle_kind_manager.hpp" +#include "graphics/stkmeshscenenode.hpp" #include "graphics/stkinstancedscenenode.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" @@ -373,11 +374,20 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node, scene::ISceneNod } else { + bool displacing = false; + if (xml_node) + xml_node->get("displacing", &displacing); + m_node = irr_driver->addMesh(m_mesh, parent); + + STKMeshSceneNode* stkmesh = dynamic_cast(m_node); + if (displacing && stkmesh != NULL) + stkmesh->setIsDisplacement(displacing); + m_frame_start = 0; m_frame_end = 0; - if (World::getWorld() != NULL && World::getWorld()->getTrack() != NULL) + if (World::getWorld() != NULL && World::getWorld()->getTrack() != NULL && xml_node != NULL) World::getWorld()->getTrack()->handleAnimatedTextures(m_node, *xml_node); } //#ifdef DEBUG @@ -486,10 +496,7 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(const XMLNode& xml_no } } else - { - fprintf(stderr, - "[TrackObject] Sound emitter object could not be created\n"); - } + Log::error("TrackObject", "Sound emitter object could not be created."); if (trigger_when_near) { @@ -743,9 +750,7 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(const m_action_active = true; if (m_action.size() == 0) - { - fprintf(stderr, "[TrackObject] WARNING: action-trigger has no action defined\n"); - } + Log::warn("TrackObject", "Action-trigger has no action defined."); ItemManager::get()->newItem(m_init_xyz, trigger_distance, this); } @@ -881,10 +886,7 @@ void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who) return; } else - { - fprintf(stderr, "[TrackObject] WARNING: unknown action <%s>\n", - m_action.c_str()); - } + Log::warn("TrackObject", "Unknown action '%s'", m_action.c_str()); } diff --git a/src/network/singleton.hpp b/src/utils/singleton.hpp similarity index 74% rename from src/network/singleton.hpp rename to src/utils/singleton.hpp index 793c74584..96ac90023 100644 --- a/src/network/singleton.hpp +++ b/src/utils/singleton.hpp @@ -31,13 +31,13 @@ * classes. */ template -class Singleton +class AbstractSingleton { protected: /*! \brief Constructor */ - Singleton () { m_singleton = NULL; } + AbstractSingleton() { m_singleton = NULL; } /*! \brief Destructor */ - virtual ~Singleton () + virtual ~AbstractSingleton() { Log::info("Singleton", "Destroyed singleton."); } @@ -72,6 +72,7 @@ class Singleton if (m_singleton) { delete m_singleton; + m_singleton = NULL; } } @@ -79,6 +80,44 @@ class Singleton static T *m_singleton; }; +template T *AbstractSingleton::m_singleton = NULL; + +template +class Singleton +{ +protected: + /*! \brief Constructor */ + Singleton() { m_singleton = NULL; } + /*! \brief Destructor */ + virtual ~Singleton() + { + Log::info("Singleton", "Destroyed singleton."); + } + +public: + /*! \brief Used to get the instance. */ + static T *getInstance() + { + if (m_singleton == NULL) + m_singleton = new T; + return m_singleton; + } + + /*! \brief Used to kill the singleton, if needed. */ + static void kill() + { + if (m_singleton) + { + delete m_singleton; + m_singleton = NULL; + } + } + +private: + static T *m_singleton; +}; + template T *Singleton::m_singleton = NULL; + #endif // SINGLETON_HPP diff --git a/src/utils/string_utils.cpp b/src/utils/string_utils.cpp index a096f88c5..091440a0c 100644 --- a/src/utils/string_utils.cpp +++ b/src/utils/string_utils.cpp @@ -520,7 +520,7 @@ namespace StringUtils // which admittedly only works for min < 100000 - which is about 68 // days - good enough. char s[12]; - sprintf ( s, "%02d:%02d:%02d", min, sec, hundredths) ; + sprintf(s, "%02d:%02d:%02d", min, sec, hundredths); return std::string(s); } // timeToString @@ -738,8 +738,8 @@ namespace StringUtils + 10*very_minor + release_candidate; - if(version<=0) - printf("Invalid version string '%s'.\n", s.c_str()); + if(version <= 0) + Log::error("StringUtils", "Invalid version string '%s'.", s.c_str()); return version; } // versionToInt