Advertisement
Guest User

Untitled

a guest
Nov 2nd, 2024
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.08 KB | None | 0 0
  1. #include <glad/glad.h>
  2. #include <GLFW/glfw3.h>
  3.  
  4. #include <glm/glm.hpp>
  5. #include <glm/gtc/matrix_transform.hpp>
  6. #include <glm/gtc/type_ptr.hpp>
  7.  
  8. #define STB_IMAGE_IMPLEMENTATION
  9. #include "../helpers/stb_image.h"
  10. #include "../helpers/shader_m.h"
  11. #include "../helpers/camera.h"
  12.  
  13.  
  14. #include <iostream>
  15. #include <random>
  16.  
  17. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  18. void mouse_callback(GLFWwindow* window, double xpos, double ypos);
  19. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
  20. void processInput(GLFWwindow *window);
  21. unsigned int loadTexture(const char *path);
  22. void renderScene(const Shader &shader);
  23. void renderCube();
  24. void renderQuad();
  25. std::vector<glm::mat4> getLightSpaceMatrices();
  26. std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& projview);
  27. void drawCascadeVolumeVisualizers(const std::vector<glm::mat4>& lightMatrices, Shader* shader);
  28. unsigned int loadCubemap(std::vector<std::string> faces);
  29.  
  30. // settings
  31. const unsigned int SCR_WIDTH = 2560;
  32. const unsigned int SCR_HEIGHT = 1440;
  33.  
  34. // framebuffer size
  35. int fb_width;
  36. int fb_height;
  37.  
  38. // camera
  39. Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
  40. float lastX = (float)SCR_WIDTH / 2.0;
  41. float lastY = (float)SCR_HEIGHT / 2.0;
  42. bool firstMouse = true;
  43. float cameraNearPlane = 0.1f;
  44. float cameraFarPlane = 500.0f;
  45.  
  46. // timing
  47. float deltaTime = 0.0f;
  48. float lastFrame = 0.0f;
  49.  
  50. std::vector<float> shadowCascadeLevels{ cameraFarPlane / 50.0f, cameraFarPlane / 25.0f, cameraFarPlane / 10.0f, cameraFarPlane / 2.0f };
  51. int debugLayer = 0;
  52.  
  53. // meshes
  54. unsigned int planeVAO;
  55.  
  56. unsigned int cubemapBlockTexture;
  57.  
  58. // lighting info
  59. // -------------
  60. const glm::vec3 lightDir = glm::normalize(glm::vec3(20.0f, 50, 20.0f));
  61. unsigned int lightFBO;
  62. unsigned int lightDepthMaps;
  63. constexpr unsigned int depthMapResolution = 4096;
  64.  
  65. bool showQuad = false;
  66.  
  67. std::random_device device;
  68. std::mt19937 generator = std::mt19937(device());
  69.  
  70. std::vector<glm::mat4> lightMatricesCache;
  71.  
  72. int main()
  73. {
  74. //generator.seed(2);
  75. // glfw: initialize and configure
  76. // ------------------------------
  77. glfwInit();
  78. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  79. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  80. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  81.  
  82. #ifdef __APPLE__
  83. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  84. #endif
  85.  
  86. // glfw window creation
  87. // --------------------
  88. GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
  89. if (window == NULL)
  90. {
  91. std::cout << "Failed to create GLFW window" << std::endl;
  92. glfwTerminate();
  93. return -1;
  94. }
  95. glfwMakeContextCurrent(window);
  96. glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
  97. glfwSetCursorPosCallback(window, mouse_callback);
  98. glfwSetScrollCallback(window, scroll_callback);
  99. glfwGetFramebufferSize(window, &fb_width, &fb_height);
  100.  
  101. // tell GLFW to capture our mouse
  102. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  103.  
  104. // glad: load all OpenGL function pointers
  105. // ---------------------------------------
  106. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  107. {
  108. std::cout << "Failed to initialize GLAD" << std::endl;
  109. return -1;
  110. }
  111.  
  112. // configure global opengl state
  113. // -----------------------------
  114. glEnable(GL_DEPTH_TEST);
  115.  
  116. // build and compile shaders
  117. // -------------------------
  118. Shader shader("../CascadedShadowMapping/10.shadow_mapping.vs", "../CascadedShadowMapping/10.shadow_mapping.fs");
  119. Shader simpleDepthShader("../CascadedShadowMapping/10.shadow_mapping_depth.vs", "../CascadedShadowMapping/10.shadow_mapping_depth.fs", "../CascadedShadowMapping/10.shadow_mapping_depth.gs");
  120. Shader debugDepthQuad("../CascadedShadowMapping/10.debug_quad.vs", "../CascadedShadowMapping/10.debug_quad_depth.fs");
  121. Shader debugCascadeShader("../CascadedShadowMapping/10.debug_cascade.vs", "../CascadedShadowMapping/10.debug_cascade.fs");
  122.  
  123. // set up vertex data (and buffer(s)) and configure vertex attributes
  124. // ------------------------------------------------------------------
  125. // float planeVertices[] = {
  126. // // positions // normals // texcoords
  127. // 25.0f, -2.0f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
  128. // -25.0f, -2.0f, 25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
  129. // -25.0f, -2.0f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f,
  130. // 25.0f, -2.0f, 25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 0.0f,
  131. // -25.0f, -2.0f, -25.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25.0f,
  132. // 25.0f, -2.0f, -25.0f, 0.0f, 1.0f, 0.0f, 25.0f, 25.0f
  133. // };
  134.  
  135. // cube map / cube faces
  136. // stbi_set_flip_vertically_on_load(false);
  137. std::vector<std::string> blockFaces
  138. { // paths are relative from the 'cmake-build-debug' directory
  139. // had to swap order of left and right textures for this set of textures
  140. "../textures/cube/side.png",
  141. "../textures/cube/side.png",
  142. "../textures/cube/top.png",
  143. "../textures/cube/bottom.png",
  144. "../textures/cube/side.png",
  145. "../textures/cube/side.png"
  146. };
  147. cubemapBlockTexture = loadCubemap(blockFaces);
  148. // stbi_set_flip_vertically_on_load(true);
  149.  
  150.  
  151. // plane VAO
  152. // unsigned int planeVBO;
  153. // glGenVertexArrays(1, &planeVAO);
  154. // glGenBuffers(1, &planeVBO);
  155. // glBindVertexArray(planeVAO);
  156. // glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
  157. // glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
  158. // glEnableVertexAttribArray(0);
  159. // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
  160. // glEnableVertexAttribArray(1);
  161. // glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
  162. // glEnableVertexAttribArray(2);
  163. // glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
  164. // glBindVertexArray(0);
  165.  
  166. // load textures
  167. // -------------
  168. // unsigned int woodTexture = loadTexture("../CascadedShadowMapping/wood.png");
  169.  
  170. // configure light FBO
  171. // -----------------------
  172. glGenFramebuffers(1, &lightFBO);
  173.  
  174. glGenTextures(1, &lightDepthMaps);
  175. glBindTexture(GL_TEXTURE_2D_ARRAY, lightDepthMaps);
  176. glTexImage3D(
  177. GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, depthMapResolution, depthMapResolution, int(shadowCascadeLevels.size()) + 1,
  178. 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
  179.  
  180. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  181. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  182. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
  183. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
  184.  
  185. constexpr float bordercolor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  186. glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, bordercolor);
  187.  
  188. glBindFramebuffer(GL_FRAMEBUFFER, lightFBO);
  189. glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, lightDepthMaps, 0);
  190. glDrawBuffer(GL_NONE);
  191. glReadBuffer(GL_NONE);
  192.  
  193. int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  194. if (status != GL_FRAMEBUFFER_COMPLETE)
  195. {
  196. std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!";
  197. throw 0;
  198. }
  199.  
  200. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  201.  
  202. // configure UBO
  203. // --------------------
  204. unsigned int matricesUBO;
  205. glGenBuffers(1, &matricesUBO);
  206. glBindBuffer(GL_UNIFORM_BUFFER, matricesUBO);
  207. glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4x4) * 16, nullptr, GL_STATIC_DRAW);
  208. glBindBufferBase(GL_UNIFORM_BUFFER, 0, matricesUBO);
  209. glBindBuffer(GL_UNIFORM_BUFFER, 0);
  210.  
  211. // shader configuration
  212. // --------------------
  213. shader.use();
  214. shader.setInt("cubeMapTexture", 0);
  215. shader.setInt("shadowMap", 1);
  216. debugDepthQuad.use();
  217. debugDepthQuad.setInt("depthMap", 0);
  218.  
  219. // render loop
  220. // -----------
  221. while (!glfwWindowShouldClose(window))
  222. {
  223. // per-frame time logic
  224. // --------------------
  225. float currentFrame = glfwGetTime();
  226. deltaTime = currentFrame - lastFrame;
  227. lastFrame = currentFrame;
  228.  
  229. // input
  230. // -----
  231. processInput(window);
  232.  
  233. // change light position over time
  234. //lightPos.x = sin(glfwGetTime()) * 3.0f;
  235. //lightPos.z = cos(glfwGetTime()) * 2.0f;
  236. //lightPos.y = 5.0 + cos(glfwGetTime()) * 1.0f;
  237.  
  238. // render
  239. // ------
  240. glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
  241. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  242.  
  243. // 0. UBO setup
  244. const auto lightMatrices = getLightSpaceMatrices();
  245. glBindBuffer(GL_UNIFORM_BUFFER, matricesUBO);
  246. for (size_t i = 0; i < lightMatrices.size(); ++i)
  247. {
  248. glBufferSubData(GL_UNIFORM_BUFFER, i * sizeof(glm::mat4x4), sizeof(glm::mat4x4), &lightMatrices[i]);
  249. }
  250. glBindBuffer(GL_UNIFORM_BUFFER, 0);
  251.  
  252. // 1. render depth of scene to texture (from light's perspective)
  253. // --------------------------------------------------------------
  254. //lightProjection = glm::perspective(glm::radians(45.0f), (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT, near_plane, far_plane); // note that if you use a perspective projection matrix you'll have to change the light position as the current light position isn't enough to reflect the whole scene
  255. // render scene from light's point of view
  256. simpleDepthShader.use();
  257.  
  258. glBindFramebuffer(GL_FRAMEBUFFER, lightFBO);
  259. glViewport(0, 0, depthMapResolution, depthMapResolution);
  260. glClear(GL_DEPTH_BUFFER_BIT);
  261. glCullFace(GL_FRONT); // peter panning
  262. renderScene(simpleDepthShader);
  263. glCullFace(GL_BACK);
  264. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  265.  
  266. // reset viewport
  267. glViewport(0, 0, fb_width, fb_height);
  268. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  269.  
  270. // 2. render scene as normal using the generated depth/shadow map
  271. // --------------------------------------------------------------
  272. glViewport(0, 0, fb_width, fb_height);
  273. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  274. shader.use();
  275. const glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)fb_width / (float)fb_height, cameraNearPlane, cameraFarPlane);
  276. const glm::mat4 view = camera.GetViewMatrix();
  277. shader.setMat4("projection", projection);
  278. shader.setMat4("view", view);
  279. // set light uniforms
  280. shader.setVec3("viewPos", camera.Position);
  281. shader.setVec3("lightDir", lightDir);
  282. shader.setFloat("farPlane", cameraFarPlane);
  283. shader.setInt("cascadeCount", shadowCascadeLevels.size());
  284. for (size_t i = 0; i < shadowCascadeLevels.size(); ++i)
  285. {
  286. shader.setFloat("cascadePlaneDistances[" + std::to_string(i) + "]", shadowCascadeLevels[i]);
  287. }
  288. glActiveTexture(GL_TEXTURE0);
  289. // glBindTexture(GL_TEXTURE_2D, woodTexture); **********************************************************************************
  290. glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapBlockTexture);
  291. glActiveTexture(GL_TEXTURE1);
  292. glBindTexture(GL_TEXTURE_2D_ARRAY, lightDepthMaps);
  293. renderScene(shader);
  294.  
  295. if (lightMatricesCache.size() != 0)
  296. {
  297. glEnable(GL_BLEND);
  298. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  299. debugCascadeShader.use();
  300. debugCascadeShader.setMat4("projection", projection);
  301. debugCascadeShader.setMat4("view", view);
  302. drawCascadeVolumeVisualizers(lightMatricesCache, &debugCascadeShader);
  303. glDisable(GL_BLEND);
  304. }
  305.  
  306. // render Depth map to quad for visual debugging
  307. // ---------------------------------------------
  308. debugDepthQuad.use();
  309. debugDepthQuad.setInt("layer", debugLayer);
  310. glActiveTexture(GL_TEXTURE0);
  311. glBindTexture(GL_TEXTURE_2D_ARRAY, lightDepthMaps);
  312. if (showQuad)
  313. {
  314. renderQuad();
  315. }
  316.  
  317. // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
  318. // -------------------------------------------------------------------------------
  319. glfwSwapBuffers(window);
  320. glfwPollEvents();
  321. }
  322.  
  323. // optional: de-allocate all resources once they've outlived their purpose:
  324. // ------------------------------------------------------------------------
  325. glDeleteVertexArrays(1, &planeVAO);
  326. // glDeleteBuffers(1, &planeVBO);
  327.  
  328. glfwTerminate();
  329. return 0;
  330. }
  331.  
  332. // renders the 3D scene
  333. // --------------------
  334. void renderScene(const Shader &shader)
  335. {
  336. // floor
  337. // glm::mat4 model = glm::mat4(1.0f);
  338. // shader.setMat4("model", model);
  339. // glBindVertexArray(planeVAO);
  340. // glDrawArrays(GL_TRIANGLES, 0, 6);
  341.  
  342. static std::vector<glm::mat4> modelMatrices;
  343. if (modelMatrices.size() == 0)
  344. {
  345. for (int i = 0; i < 100; ++i)
  346. {
  347. static std::uniform_real_distribution<float> offsetDistribution = std::uniform_real_distribution<float>(-10, 10);
  348. static std::uniform_real_distribution<float> scaleDistribution = std::uniform_real_distribution<float>(1.0, 2.0);
  349. static std::uniform_real_distribution<float> rotationDistribution = std::uniform_real_distribution<float>(0, 180);
  350.  
  351. auto model = glm::mat4(1.0f);
  352. model = glm::translate(model, glm::vec3(offsetDistribution(generator), offsetDistribution(generator) + 10.0f, offsetDistribution(generator)));
  353. // model = glm::rotate(model, glm::radians(rotationDistribution(generator)), glm::normalize(glm::vec3(1.0, 0.0, 1.0)));
  354. model = glm::scale(model, glm::vec3(scaleDistribution(generator)));
  355. modelMatrices.push_back(model);
  356. }
  357. }
  358.  
  359. for (const auto& model : modelMatrices)
  360. {
  361. shader.setMat4("model", model);
  362. renderCube();
  363. }
  364. }
  365.  
  366.  
  367. // renderCube() renders a 1x1 3D cube in NDC.
  368. // -------------------------------------------------
  369. unsigned int cubeVAO = 0;
  370. unsigned int cubeVBO = 0;
  371. void renderCube()
  372. {
  373. // initialize (if necessary)
  374. if (cubeVAO == 0)
  375. {
  376. float vertices[] = {
  377. // Data includes normals
  378. // Back face
  379. -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  380. 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  381. 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  382. 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  383. -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  384. -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
  385. // Front face
  386. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  387. 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  388. 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  389. 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  390. -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  391. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
  392. // Left face
  393. -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
  394. -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
  395. -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
  396. -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
  397. -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
  398. -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
  399. // Right face
  400. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
  401. 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
  402. 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
  403. 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
  404. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
  405. 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
  406. // Bottom face
  407. -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
  408. 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
  409. 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
  410. 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
  411. -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
  412. -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
  413. // Top face
  414. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
  415. 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
  416. 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
  417. 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
  418. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
  419. -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f
  420. };
  421. glGenVertexArrays(1, &cubeVAO);
  422. glGenBuffers(1, &cubeVBO);
  423. // fill buffer
  424. glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
  425. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  426. // link vertex attributes
  427. glBindVertexArray(cubeVAO);
  428. // position attribute
  429. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
  430. glEnableVertexAttribArray(0);
  431. // normal attribute
  432. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
  433. glEnableVertexAttribArray(1);
  434.  
  435. // glEnableVertexAttribArray(0);
  436. // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
  437. // glEnableVertexAttribArray(1);
  438. // glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
  439. // glEnableVertexAttribArray(2);
  440. // glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
  441. // glBindBuffer(GL_ARRAY_BUFFER, 0);
  442. glBindVertexArray(0);
  443. }
  444. // render Cube
  445. glBindVertexArray(cubeVAO);
  446. // glActiveTexture(GL_TEXTURE0);
  447. glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapBlockTexture);
  448. glDrawArrays(GL_TRIANGLES, 0, 36);
  449. glBindVertexArray(0);
  450. }
  451.  
  452. // renderQuad() renders a 1x1 XY quad in NDC
  453. // -----------------------------------------
  454. unsigned int quadVAO = 0;
  455. unsigned int quadVBO;
  456. void renderQuad()
  457. {
  458. if (quadVAO == 0)
  459. {
  460. float quadVertices[] = {
  461. // positions // texture Coords
  462. -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
  463. -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
  464. 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
  465. 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
  466. };
  467. // setup plane VAO
  468. glGenVertexArrays(1, &quadVAO);
  469. glGenBuffers(1, &quadVBO);
  470. glBindVertexArray(quadVAO);
  471. glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
  472. glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
  473. glEnableVertexAttribArray(0);
  474. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
  475. glEnableVertexAttribArray(1);
  476. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
  477. }
  478. glBindVertexArray(quadVAO);
  479. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  480. glBindVertexArray(0);
  481. }
  482.  
  483. std::vector<GLuint> visualizerVAOs;
  484. std::vector<GLuint> visualizerVBOs;
  485. std::vector<GLuint> visualizerEBOs;
  486. void drawCascadeVolumeVisualizers(const std::vector<glm::mat4>& lightMatrices, Shader* shader)
  487. {
  488. visualizerVAOs.resize(8);
  489. visualizerEBOs.resize(8);
  490. visualizerVBOs.resize(8);
  491.  
  492. const GLuint indices[] = {
  493. 0, 2, 3,
  494. 0, 3, 1,
  495. 4, 6, 2,
  496. 4, 2, 0,
  497. 5, 7, 6,
  498. 5, 6, 4,
  499. 1, 3, 7,
  500. 1, 7, 5,
  501. 6, 7, 3,
  502. 6, 3, 2,
  503. 1, 5, 4,
  504. 0, 1, 4
  505. };
  506.  
  507. const glm::vec4 colors[] = {
  508. {1.0, 0.0, 0.0, 0.5f},
  509. {0.0, 1.0, 0.0, 0.5f},
  510. {0.0, 0.0, 1.0, 0.5f},
  511. };
  512.  
  513. for (int i = 0; i < lightMatrices.size(); ++i)
  514. {
  515. const auto corners = getFrustumCornersWorldSpace(lightMatrices[i]);
  516. std::vector<glm::vec3> vec3s;
  517. for (const auto& v : corners)
  518. {
  519. vec3s.push_back(glm::vec3(v));
  520. }
  521.  
  522. glGenVertexArrays(1, &visualizerVAOs[i]);
  523. glGenBuffers(1, &visualizerVBOs[i]);
  524. glGenBuffers(1, &visualizerEBOs[i]);
  525.  
  526. glBindVertexArray(visualizerVAOs[i]);
  527.  
  528. glBindBuffer(GL_ARRAY_BUFFER, visualizerVBOs[i]);
  529. glBufferData(GL_ARRAY_BUFFER, vec3s.size() * sizeof(glm::vec3), &vec3s[0], GL_STATIC_DRAW);
  530.  
  531. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, visualizerEBOs[i]);
  532. glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
  533.  
  534. glEnableVertexAttribArray(0);
  535. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
  536.  
  537. glBindVertexArray(visualizerVAOs[i]);
  538. shader->setVec4("color", colors[i % 3]);
  539. glDrawElements(GL_TRIANGLES, GLsizei(36), GL_UNSIGNED_INT, 0);
  540.  
  541. glDeleteBuffers(1, &visualizerVBOs[i]);
  542. glDeleteBuffers(1, &visualizerEBOs[i]);
  543. glDeleteVertexArrays(1, &visualizerVAOs[i]);
  544.  
  545. glBindVertexArray(0);
  546. }
  547.  
  548. visualizerVAOs.clear();
  549. visualizerEBOs.clear();
  550. visualizerVBOs.clear();
  551. }
  552.  
  553. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
  554. // ---------------------------------------------------------------------------------------------------------
  555. void processInput(GLFWwindow *window)
  556. {
  557. if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  558. glfwSetWindowShouldClose(window, true);
  559.  
  560. camera.MovementSpeed = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS ? 2.5 * 10 : 2.5;
  561.  
  562. if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
  563. camera.ProcessKeyboard(FORWARD, deltaTime);
  564. if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
  565. camera.ProcessKeyboard(BACKWARD, deltaTime);
  566. if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
  567. camera.ProcessKeyboard(LEFT, deltaTime);
  568. if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
  569. camera.ProcessKeyboard(RIGHT, deltaTime);
  570. if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
  571. camera.ProcessKeyboard(UP, deltaTime);
  572. if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
  573. camera.ProcessKeyboard(DOWN, deltaTime);
  574.  
  575. static int fPress = GLFW_RELEASE;
  576. if (glfwGetKey(window, GLFW_KEY_F) == GLFW_RELEASE && fPress == GLFW_PRESS)
  577. {
  578. showQuad = !showQuad;
  579. }
  580. fPress = glfwGetKey(window, GLFW_KEY_F);
  581.  
  582. static int plusPress = GLFW_RELEASE;
  583. if (glfwGetKey(window, GLFW_KEY_N) == GLFW_RELEASE && plusPress == GLFW_PRESS)
  584. {
  585. debugLayer++;
  586. if (debugLayer > shadowCascadeLevels.size())
  587. {
  588. debugLayer = 0;
  589. }
  590. }
  591. plusPress = glfwGetKey(window, GLFW_KEY_N);
  592.  
  593. static int cPress = GLFW_RELEASE;
  594. if (glfwGetKey(window, GLFW_KEY_C) == GLFW_RELEASE && cPress == GLFW_PRESS)
  595. {
  596. lightMatricesCache = getLightSpaceMatrices();
  597. }
  598. cPress = glfwGetKey(window, GLFW_KEY_C);
  599. }
  600.  
  601. // glfw: whenever the window size changed (by OS or user resize) this callback function executes
  602. // ---------------------------------------------------------------------------------------------
  603. void framebuffer_size_callback(GLFWwindow* window, int width, int height)
  604. {
  605. // make sure the viewport matches the new window dimensions; note that width and
  606. // height will be significantly larger than specified on retina displays.
  607. fb_width = width;
  608. fb_height = height;
  609. glViewport(0, 0, width, height);
  610. }
  611.  
  612. // glfw: whenever the mouse moves, this callback is called
  613. // -------------------------------------------------------
  614. void mouse_callback(GLFWwindow* window, double xpos, double ypos)
  615. {
  616. if (firstMouse)
  617. {
  618. lastX = xpos;
  619. lastY = ypos;
  620. firstMouse = false;
  621. }
  622.  
  623. float xoffset = xpos - lastX;
  624. float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
  625.  
  626. lastX = xpos;
  627. lastY = ypos;
  628.  
  629. camera.ProcessMouseMovement(xoffset, yoffset);
  630. }
  631.  
  632. // glfw: whenever the mouse scroll wheel scrolls, this callback is called
  633. // ----------------------------------------------------------------------
  634. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
  635. {
  636. camera.ProcessMouseScroll(yoffset);
  637. }
  638.  
  639. // utility function for loading a 2D texture from file
  640. // ---------------------------------------------------
  641. unsigned int loadTexture(char const * path)
  642. {
  643. unsigned int textureID;
  644. glGenTextures(1, &textureID);
  645.  
  646. int width, height, nrComponents;
  647. unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
  648. if (data)
  649. {
  650. GLenum format;
  651. if (nrComponents == 1)
  652. format = GL_RED;
  653. else if (nrComponents == 3)
  654. format = GL_RGB;
  655. else if (nrComponents == 4)
  656. format = GL_RGBA;
  657.  
  658. glBindTexture(GL_TEXTURE_2D, textureID);
  659. glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
  660. glGenerateMipmap(GL_TEXTURE_2D);
  661.  
  662. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT); // for this tutorial: use GL_CLAMP_TO_EDGE to prevent semi-transparent borders. Due to interpolation it takes texels from next repeat
  663. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT);
  664. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  665. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  666.  
  667. stbi_image_free(data);
  668. }
  669. else
  670. {
  671. std::cout << "Texture failed to load at path: " << path << std::endl;
  672. stbi_image_free(data);
  673. }
  674.  
  675. return textureID;
  676. }
  677.  
  678. std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& projview)
  679. {
  680. const auto inv = glm::inverse(projview);
  681.  
  682. std::vector<glm::vec4> frustumCorners;
  683. for (unsigned int x = 0; x < 2; ++x)
  684. {
  685. for (unsigned int y = 0; y < 2; ++y)
  686. {
  687. for (unsigned int z = 0; z < 2; ++z)
  688. {
  689. const glm::vec4 pt = inv * glm::vec4(2.0f * x - 1.0f, 2.0f * y - 1.0f, 2.0f * z - 1.0f, 1.0f);
  690. frustumCorners.push_back(pt / pt.w);
  691. }
  692. }
  693. }
  694.  
  695. return frustumCorners;
  696. }
  697.  
  698.  
  699. std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& proj, const glm::mat4& view)
  700. {
  701. return getFrustumCornersWorldSpace(proj * view);
  702. }
  703.  
  704. glm::mat4 getLightSpaceMatrix(const float nearPlane, const float farPlane)
  705. {
  706. const auto proj = glm::perspective(
  707. glm::radians(camera.Zoom), (float)fb_width / (float)fb_height, nearPlane,
  708. farPlane);
  709. const auto corners = getFrustumCornersWorldSpace(proj, camera.GetViewMatrix());
  710.  
  711. glm::vec3 center = glm::vec3(0, 0, 0);
  712. for (const auto& v : corners)
  713. {
  714. center += glm::vec3(v);
  715. }
  716. center /= corners.size();
  717.  
  718. const auto lightView = glm::lookAt(center + lightDir, center, glm::vec3(0.0f, 1.0f, 0.0f));
  719.  
  720. float minX = std::numeric_limits<float>::max();
  721. float maxX = std::numeric_limits<float>::lowest();
  722. float minY = std::numeric_limits<float>::max();
  723. float maxY = std::numeric_limits<float>::lowest();
  724. float minZ = std::numeric_limits<float>::max();
  725. float maxZ = std::numeric_limits<float>::lowest();
  726. for (const auto& v : corners)
  727. {
  728. const auto trf = lightView * v;
  729. minX = std::min(minX, trf.x);
  730. maxX = std::max(maxX, trf.x);
  731. minY = std::min(minY, trf.y);
  732. maxY = std::max(maxY, trf.y);
  733. minZ = std::min(minZ, trf.z);
  734. maxZ = std::max(maxZ, trf.z);
  735. }
  736.  
  737. // Tune this parameter according to the scene
  738. constexpr float zMult = 10.0f;
  739. if (minZ < 0)
  740. {
  741. minZ *= zMult;
  742. }
  743. else
  744. {
  745. minZ /= zMult;
  746. }
  747. if (maxZ < 0)
  748. {
  749. maxZ /= zMult;
  750. }
  751. else
  752. {
  753. maxZ *= zMult;
  754. }
  755.  
  756. const glm::mat4 lightProjection = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
  757. return lightProjection * lightView;
  758. }
  759.  
  760. std::vector<glm::mat4> getLightSpaceMatrices()
  761. {
  762. std::vector<glm::mat4> ret;
  763. for (size_t i = 0; i < shadowCascadeLevels.size() + 1; ++i)
  764. {
  765. if (i == 0)
  766. {
  767. ret.push_back(getLightSpaceMatrix(cameraNearPlane, shadowCascadeLevels[i]));
  768. }
  769. else if (i < shadowCascadeLevels.size())
  770. {
  771. ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], shadowCascadeLevels[i]));
  772. }
  773. else
  774. {
  775. ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], cameraFarPlane));
  776. }
  777. }
  778. return ret;
  779. }
  780.  
  781. unsigned int loadCubemap(std::vector<std::string> faces)
  782. {
  783. unsigned int textureID;
  784. glGenTextures(1, &textureID);
  785. glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
  786.  
  787. int width, height, nrChannels;
  788. for (unsigned int i = 0; i < faces.size(); i++)
  789. {
  790. unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
  791. if (data)
  792. {
  793. GLenum format {};
  794. if (nrChannels == 1)
  795. format = GL_RED;
  796. else if (nrChannels == 3)
  797. format = GL_RGB;
  798. else if (nrChannels == 4)
  799. format = GL_RGBA;
  800.  
  801. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
  802. 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data
  803. );
  804. stbi_image_free(data);
  805. std::cout << "cube texture num of channels: " << nrChannels << std::endl;
  806. }
  807. else
  808. {
  809. std::cout << "Cubemap tex failed to load at path: " << faces[i] << std::endl;
  810. stbi_image_free(data);
  811. }
  812. }
  813. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  814. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  815. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  816. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  817. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
  818.  
  819. return textureID;
  820. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement