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

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