Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Render.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*!
  2. * \file src/Render.cpp
  3. * \brief World Renderer
  4. *
  5. * \author Mongoose
  6. * \author xythobuz
  7. */
  8. #include <fstream>
  9. #include <sstream>
  10. #include "global.h"
  11. #include "Camera.h"
  12. #include "Log.h"
  13. #include "Menu.h"
  14. #include "StaticMesh.h"
  15. #include "World.h"
  16. #include "system/Shader.h"
  17. #include "system/Window.h"
  18. #include "Render.h"
  19. #include <glm/gtc/matrix_transform.hpp>
  20. #include <glbinding/gl/gl33.h>
  21. #include "imgui/imgui.h"
  22. #include "stb/stb_image_write.h"
  23. RenderMode Render::mode = RenderMode::LoadScreen;
  24. std::vector<Room*> Render::roomList;
  25. bool Render::displayViewFrustum = false;
  26. bool Render::displayVisibilityCheck = false;
  27. void Render::display() {
  28. gl::glClear(gl::GL_COLOR_BUFFER_BIT | gl::GL_DEPTH_BUFFER_BIT);
  29. if (mode == RenderMode::LoadScreen) {
  30. ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
  31. ImGui::SetNextWindowSize(ImVec2(Window::getSize().x, Window::getSize().y));
  32. ImGui::Begin("SplashWindow", nullptr, ImGuiWindowFlags_NoTitleBar
  33. | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove
  34. | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
  35. | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
  36. auto bm = TextureManager::getBufferManager(TEXTURE_SPLASH, TextureStorage::SYSTEM);
  37. ImGui::Image(bm, ImVec2(Window::getSize().x, Window::getSize().y));
  38. ImGui::End();
  39. return;
  40. }
  41. if (mode == RenderMode::Wireframe) {
  42. gl::glPolygonMode(gl::GL_FRONT_AND_BACK, gl::GL_LINE);
  43. } else {
  44. gl::glPolygonMode(gl::GL_FRONT_AND_BACK, gl::GL_FILL);
  45. }
  46. bool updated = Camera::update();
  47. glm::mat4 projection = Camera::getProjectionMatrix();
  48. glm::mat4 view = Camera::getViewMatrix();
  49. glm::mat4 VP = projection * view;
  50. if (updated || displayVisibilityCheck) {
  51. int r = Camera::getRoom();
  52. clearRoomList();
  53. if (r < 0) {
  54. buildRoomList(VP);
  55. } else {
  56. buildRoomList(VP, r);
  57. }
  58. }
  59. for (int r = roomList.size() - 1; r >= 0; r--) {
  60. roomList.at(r)->display(VP);
  61. for (int i = 0; i < World::sizeEntity(); i++) {
  62. auto& e = World::getEntity(i);
  63. if (roomList.at(r)->getIndex() == e.getRoom()) {
  64. e.display(VP);
  65. }
  66. }
  67. }
  68. if (displayViewFrustum)
  69. Camera::displayFrustum(VP);
  70. if (mode == RenderMode::Wireframe) {
  71. gl::glPolygonMode(gl::GL_FRONT_AND_BACK, gl::GL_FILL);
  72. }
  73. }
  74. void Render::buildRoomList(glm::mat4 VP, int room, glm::vec2 min, glm::vec2 max) {
  75. if (room < -1) {
  76. // Check if the camera currently is in a room...
  77. for (int i = 0; i < World::sizeRoom(); i++) {
  78. if (World::getRoom(i).getBoundingBox().inBox(Camera::getPosition())) {
  79. buildRoomList(VP, i);
  80. return;
  81. }
  82. }
  83. buildRoomList(VP, -1);
  84. } else if (room == -1) {
  85. // Check visibility for all rooms!
  86. for (int i = 0; i < World::sizeRoom(); i++) {
  87. if (Camera::boxInFrustum(World::getRoom(i).getBoundingBox())) {
  88. roomList.push_back(&World::getRoom(i));
  89. }
  90. }
  91. } else {
  92. roomList.push_back(&World::getRoom(room));
  93. if (displayVisibilityCheck) {
  94. // Display the visibility test for the portal to this room
  95. BoundingBox debugBox(glm::vec3(min, 0.0f), glm::vec3(max, 0.0f));
  96. debugBox.display(glm::mat4(1.0f), glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
  97. ImGui::Text(" Min: %.3f %.3f", min.x, min.y);
  98. ImGui::Text(" Max: %.3f %.3f", max.x, max.y);
  99. }
  100. // Check all portals leading from this room to somewhere else
  101. for (int i = 0; i < World::getRoom(room).sizePortals(); i++) {
  102. auto& portal = World::getRoom(room).getPortal(i);
  103. // Calculate the 2D window of this portal
  104. glm::vec3 newMin, newMax;
  105. for (int c = 0; c < 4; c++) {
  106. glm::vec3 vert = portal.getVertex(c);
  107. glm::vec4 result = VP * glm::vec4(vert, 1.0f);
  108. vert = glm::vec3(result) / result.w;
  109. if (displayVisibilityCheck) {
  110. ImGui::Text("Test %d: %.3f %.3f %.3f", c, vert.x, vert.y, vert.z);
  111. }
  112. if (c == 0) {
  113. newMin = vert;
  114. newMax = vert;
  115. } else {
  116. if (vert.x < newMin.x)
  117. newMin.x = vert.x;
  118. if (vert.y < newMin.y)
  119. newMin.y = vert.y;
  120. if (vert.z < newMin.z)
  121. newMin.z = vert.z;
  122. if (vert.x > newMax.x)
  123. newMax.x = vert.x;
  124. if (vert.y > newMax.y)
  125. newMax.y = vert.y;
  126. if (vert.z > newMax.z)
  127. newMax.z = vert.z;
  128. }
  129. }
  130. if (displayVisibilityCheck) {
  131. ImGui::Text("NewMin: %.3f %.3f %.3f", newMin.x, newMin.y, newMin.z);
  132. ImGui::Text("NewMax: %.3f %.3f %.3f", newMax.x, newMax.y, newMax.z);
  133. }
  134. //! \fixme Currently also checking behind player, because Z is always 1.0f?!
  135. //if ((newMin.z > 0.0f) || (newMin.z < -1.0f) || (newMax.z > 0.0f) || (newMax.z < -1.0f)) {
  136. // continue;
  137. //}
  138. // Check if the portal intersects the portal leading into this room
  139. if (!((min.x < newMax.x) && (max.x > newMin.x)
  140. && (min.y < newMax.y) && (max.y > newMin.y))) {
  141. continue;
  142. }
  143. // Check if this room is already in the list...
  144. bool found = false;
  145. for (int n = 0; n < roomList.size(); n++) {
  146. if (roomList.at(n) == &World::getRoom(portal.getAdjoiningRoom())) {
  147. found = true;
  148. break;
  149. }
  150. }
  151. // ...only render it if it is not
  152. if (!found) {
  153. buildRoomList(VP, portal.getAdjoiningRoom(), glm::vec2(newMin), glm::vec2(newMax));
  154. }
  155. }
  156. }
  157. }
  158. void Render::screenShot(const char* filenameBase) {
  159. orAssert(filenameBase != nullptr);
  160. int w = Window::getSize().x;
  161. int h = Window::getSize().y;
  162. int sz = w * h;
  163. unsigned char* image = new unsigned char[sz * 3];
  164. gl::glReadPixels(0, 0, w, h, gl::GL_RGB, gl::GL_UNSIGNED_BYTE, image);
  165. unsigned char* buffer = new unsigned char[sz * 3];
  166. for (int x = 0; x < w; x++) {
  167. for (int y = 0; y < h; y++) {
  168. buffer[3 * (x + (y * w))] = image[3 * (x + ((h - y - 1) * w))];
  169. buffer[(3 * (x + (y * w))) + 1] = image[(3 * (x + ((h - y - 1) * w))) + 1];
  170. buffer[(3 * (x + (y * w))) + 2] = image[(3 * (x + ((h - y - 1) * w))) + 2];
  171. }
  172. }
  173. // Don't overwrite files
  174. static int count = 0;
  175. bool done = false;
  176. std::string f;
  177. while (!done) {
  178. std::ostringstream filename;
  179. filename << filenameBase << "-" << count++ << ".png";
  180. f = filename.str();
  181. std::ifstream fs(f);
  182. done = !fs.good();
  183. fs.close();
  184. }
  185. if (!stbi_write_png(f.c_str(), w, h, 3, buffer, 0)) {
  186. Log::get(LOG_ERROR) << "Error saving image \"" << f << "\"!" << Log::endl;
  187. }
  188. delete [] image;
  189. delete [] buffer;
  190. }
  191. static const int modeStringCount = 4;
  192. static const char* modeStrings[modeStringCount] = {
  193. "Splash", "Texture", "Wireframe", "Solid"
  194. };
  195. void Render::displayUI() {
  196. if (ImGui::CollapsingHeader("Render Settings##render")) {
  197. int item = 0;
  198. if (mode == RenderMode::Texture)
  199. item = 1;
  200. else if (mode == RenderMode::Wireframe)
  201. item = 2;
  202. else if (mode == RenderMode::Solid)
  203. item = 3;
  204. if (ImGui::Combo("Render Mode##render", &item, modeStrings, modeStringCount)) {
  205. if (item == 0)
  206. mode = RenderMode::LoadScreen;
  207. else if (item == 1)
  208. mode = RenderMode::Texture;
  209. else if (item == 2)
  210. mode = RenderMode::Wireframe;
  211. else if (item == 3)
  212. mode = RenderMode::Solid;
  213. }
  214. ImGui::Separator();
  215. ImGui::Text("Camera:");
  216. bool updateViewFrustum = Camera::getUpdateViewFrustum();
  217. if (ImGui::Checkbox("Update Frustum##render", &updateViewFrustum)) {
  218. Camera::setUpdateViewFrustum(updateViewFrustum);
  219. }
  220. ImGui::SameLine();
  221. ImGui::Checkbox("Show Frustum##render", &displayViewFrustum);
  222. ImGui::SameLine();
  223. bool showOverlay = Camera::getShowOverlay();
  224. if (ImGui::Checkbox("Overlay", &showOverlay)) {
  225. Camera::setShowOverlay(showOverlay);
  226. }
  227. glm::vec3 camPos = Camera::getPosition();
  228. if (ImGui::SliderFloat3("Position", &camPos.x, -100000, 100000)) {
  229. Camera::setPosition(camPos);
  230. }
  231. ImGui::Separator();
  232. ImGui::Text("Bounding Boxes:");
  233. bool showBoundingBox = Room::getShowBoundingBox();
  234. if (ImGui::Checkbox("Rooms##bbox", &showBoundingBox)) {
  235. Room::setShowBoundingBox(showBoundingBox);
  236. }
  237. ImGui::SameLine();
  238. bool showBoundingBox2 = StaticMesh::getShowBoundingBox();
  239. if (ImGui::Checkbox("StaticMeshes##bbox", &showBoundingBox2)) {
  240. StaticMesh::setShowBoundingBox(showBoundingBox2);
  241. }
  242. ImGui::SameLine();
  243. bool showBoundingBox3 = Portal::getShowBoundingBox();
  244. if (ImGui::Checkbox("Portals##bbox", &showBoundingBox3)) {
  245. Portal::setShowBoundingBox(showBoundingBox3);
  246. }
  247. ImGui::SameLine();
  248. ImGui::Checkbox("VisChecks##bbox", &displayVisibilityCheck);
  249. ImGui::Separator();
  250. ImGui::Text("Renderable Objects:");
  251. ImGui::Text("Room: ");
  252. ImGui::SameLine();
  253. bool showRoomGeometry = Room::getShowRoomGeometry();
  254. if (ImGui::Checkbox("Geometry##renderroom", &showRoomGeometry)) {
  255. Room::setShowRoomGeometry(showRoomGeometry);
  256. }
  257. ImGui::SameLine();
  258. bool showRoomModels = Room::getShowRoomModels();
  259. if (ImGui::Checkbox("Models##renderroom", &showRoomModels)) {
  260. Room::setShowRoomModels(showRoomModels);
  261. }
  262. ImGui::SameLine();
  263. bool showRoomSprites = Room::getShowRoomSprites();
  264. if (ImGui::Checkbox("Sprites##renderroom", &showRoomSprites)) {
  265. Room::setShowRoomSprites(showRoomSprites);
  266. }
  267. ImGui::Text("Entity: ");
  268. ImGui::SameLine();
  269. bool showEntitySprites = Entity::getShowEntitySprites();
  270. if (ImGui::Checkbox("Sprites##renderentity", &showEntitySprites)) {
  271. Entity::setShowEntitySprites(showEntitySprites);
  272. }
  273. ImGui::SameLine();
  274. bool showEntityMeshes = Entity::getShowEntityMeshes();
  275. if (ImGui::Checkbox("Meshes##renderentity", &showEntityMeshes)) {
  276. Entity::setShowEntityMeshes(showEntityMeshes);
  277. }
  278. ImGui::SameLine();
  279. bool showEntityModels = Entity::getShowEntityModels();
  280. if (ImGui::Checkbox("Models##renderentity", &showEntityModels)) {
  281. Entity::setShowEntityModels(showEntityModels);
  282. }
  283. ImGui::Separator();
  284. if (ImGui::Button("New Splash##render")) {
  285. TextureManager::initializeSplash();
  286. }
  287. ImGui::SameLine();
  288. if (ImGui::Button("New Menu##render")) {
  289. Menu::initialize();
  290. }
  291. }
  292. }