Advertisement
Guest User

tings

a guest
May 21st, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.28 KB | None | 0 0
  1. #include "Shadows.h"
  2. #include "Gizmos.h"
  3. #include "Utilities.h"
  4. #include "gl_core_4_4.h"
  5. #include <GLFW/glfw3.h>
  6. #include <glm/ext.hpp>
  7. #include <iostream>
  8. #include "imgui.h"
  9. #include "imgui_tabs.h"
  10.  
  11. #define DEFAULT_SCREENWIDTH 1280
  12. #define DEFAULT_SCREENHEIGHT 720
  13.  
  14. #define SHADOW_BUFFER_SIZE 1024
  15.  
  16. Shadows::Shadows()
  17. {
  18.  
  19. }
  20.  
  21. Shadows::~Shadows()
  22. {
  23.  
  24. }
  25.  
  26. bool Shadows::onCreate()
  27. {
  28. // initialise the Gizmos helper class
  29. Gizmos::create();
  30.  
  31. //Load the shaders for this program
  32. unsigned int vertexShader = Utility::loadShader("./shaders/vertex.glsl", GL_VERTEX_SHADER);
  33. unsigned int fragmentShader = Utility::loadShader("./shaders/fragment.glsl", GL_FRAGMENT_SHADER);
  34. //Define the input and output varialbes in the shaders
  35. //Note: these names are taken from the glsl files -- added in inputs for UV coordinates
  36. const char* szInputs[] = { "Position", "Colour", "Normal","Tex1" };
  37. const char* szOutputs[] = { "FragColor" };
  38. //bind the shaders to create our shader program
  39. m_programID = Utility::createProgram(
  40. vertexShader,
  41. 0,
  42. 0,
  43. 0,
  44. fragmentShader,
  45. 4, szInputs, 1, szOutputs);
  46.  
  47. glDeleteShader(vertexShader);
  48. glDeleteShader(fragmentShader);
  49.  
  50. //Load the shaders for rendering the shadows
  51. vertexShader = Utility::loadShader("./shaders/vertex_shadow.glsl", GL_VERTEX_SHADER);
  52. fragmentShader = Utility::loadShader("./shaders/fragment_shadow.glsl", GL_FRAGMENT_SHADER);
  53. //Define the input and output varialbes in the shaders
  54. //Note: these names are taken from the glsl files -- added in inputs for UV coordinates
  55. const char* szInputs2[] = { "Position", "Colour", "Normal","Tex1" };
  56. const char* szOutputs2[] = { "FragDepth" };
  57. //bind the shaders to create our shader program
  58. m_shadowProgramID = Utility::createProgram(
  59. vertexShader,
  60. 0,
  61. 0,
  62. 0,
  63. fragmentShader,
  64. 4, szInputs2, 1, szOutputs2);
  65.  
  66. glDeleteShader(vertexShader);
  67. glDeleteShader(fragmentShader);
  68.  
  69.  
  70. m_fbxModel = new FBXFile();
  71. m_fbxModel->load("./models/ruinedtank/tank.fbx", FBXFile::UNITS_DECIMETER);
  72.  
  73. //Generate our OpenGL Vertex and Index Buffers for rendering our FBX Model Data
  74. // OPENGL: genorate the VBO, IBO and VAO
  75. glGenBuffers(1, &m_vbo);
  76. glGenBuffers(1, &m_ibo);
  77. glGenVertexArrays(1, &m_vao);
  78.  
  79. // OPENGL: Bind VAO, and then bind the VBO and IBO to the VAO
  80. glBindVertexArray(m_vao);
  81. glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
  82. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
  83.  
  84. //There is no need to populate the vbo & ibo buffers with any data at this stage
  85. //this can be done when rendering each mesh component of the FBX model
  86.  
  87. // enable the attribute locations that will be used on our shaders
  88. glEnableVertexAttribArray(0); //Pos
  89. glEnableVertexAttribArray(1); //Col
  90. glEnableVertexAttribArray(2); //Norm
  91. glEnableVertexAttribArray(3); //Tex1
  92.  
  93.  
  94. // tell our shaders where the information within our buffers lie
  95. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(FBXVertex), ((char *)0) + FBXVertex::PositionOffset);
  96. glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, sizeof(FBXVertex), ((char *)0) + FBXVertex::ColourOffset);
  97. glVertexAttribPointer(2, 4, GL_FLOAT, GL_TRUE, sizeof(FBXVertex), ((char *)0) + FBXVertex::NormalOffset);
  98. glVertexAttribPointer(3, 2, GL_FLOAT, GL_TRUE, sizeof(FBXVertex), ((char *)0) + FBXVertex::TexCoord1Offset);
  99.  
  100. // finally, where done describing our mesh to the shader
  101. // we can describe the next mesh
  102. glBindVertexArray(0);
  103. glBindBuffer(GL_ARRAY_BUFFER, 0);
  104. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  105.  
  106. //\===========================================================================================================
  107. //\Set up the frame buffer for rendering our shadows into
  108. m_FBO_texture = -1;
  109. SetupFrameBuffer(m_FBO, SHADOW_BUFFER_SIZE, SHADOW_BUFFER_SIZE, m_FBO_texture, m_FBO_depth_texture);
  110. //\===========================================================================================================
  111. //create a texture to hold the linear depth buffer samples
  112. //texture for linear depth buffer visualisation
  113.  
  114. // create a world-space matrix for a camera
  115. m_cameraMatrix = glm::inverse(glm::lookAt(glm::vec3(10, 10, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)));
  116.  
  117. // create a perspective projection matrix with a 90 degree field-of-view and widescreen aspect ratio
  118. m_projectionMatrix = glm::perspective(glm::pi<float>() * 0.25f, DEFAULT_SCREENWIDTH / (float)DEFAULT_SCREENHEIGHT, 0.1f, 1000.0f);
  119.  
  120. m_modelMatrix = glm::mat4();
  121.  
  122. // set the clear colour and enable depth testing and backface culling
  123. glClearColor(0.25f, 0.25f, 0.25f, 1.f);
  124. glEnable(GL_DEPTH_TEST);
  125. glEnable(GL_CULL_FACE);
  126.  
  127. m_lightPos = glm::vec4(50.f, 25.f, 0.f, 1.f);
  128.  
  129. return true;
  130. }
  131.  
  132. void Shadows::Update(float a_deltaTime)
  133. {
  134. // update our camera matrix using the keyboard/mouse
  135. Utility::freeMovement(m_cameraMatrix, a_deltaTime, 10);
  136.  
  137. // clear all gizmos from last frame
  138. Gizmos::clear();
  139.  
  140. // add an identity matrix gizmo
  141. Gizmos::addTransform(glm::mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1));
  142.  
  143. // rotate point
  144. float s = sinf(a_deltaTime * 0.2f);
  145. float c = cosf(a_deltaTime * 0.2f);
  146. glm::vec4 temp = m_lightPos;
  147. m_lightPos.x = temp.x * c - temp.z * s;
  148. m_lightPos.z = temp.x * s + temp.z * c;
  149. m_lightPos.w = 0;
  150. m_lightPos = glm::normalize(m_lightPos) * 25.f;
  151. Gizmos::addBox(m_lightPos.xyz, glm::vec3(0.2f, 0.2f, 0.2f), true, glm::vec4(1.0f, 0.85f, 0.05f, 1.f));
  152.  
  153. //Update the shadow projection view matrix
  154. glm::mat4 depthViewMatrix = glm::lookAt(glm::vec3(m_lightPos.xyz),
  155. glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
  156. glm::mat4 depthProjectionMatrix = glm::ortho<float>(-20, 20, -20, 20, -100, 100);
  157.  
  158. m_shadowProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
  159.  
  160. //Update our FBX model
  161. for (unsigned int i = 0; i < m_fbxModel->getMeshCount(); ++i)
  162. {
  163. // get the current mesh
  164. FBXMeshNode *mesh = m_fbxModel->getMeshByIndex(i);
  165. // if you move an object around within your scene
  166. // children nodes are not updated until this function is called.
  167. mesh->updateGlobalTransform();
  168. }
  169.  
  170. //\==========================================================================================================
  171. //\ ImGui render view to show what is held in the FBO texture position
  172. //\==========================================================================================================
  173. ImGui::Begin("Frame Rate");
  174. ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
  175. ImGui::End();
  176.  
  177. ImGui::SetNextWindowPos(ImVec2(DEFAULT_SCREENWIDTH - DEFAULT_SCREENWIDTH*0.3, DEFAULT_SCREENHEIGHT - DEFAULT_SCREENHEIGHT*0.4));
  178. ImGui::SetNextWindowSize(ImVec2(DEFAULT_SCREENWIDTH*0.3, DEFAULT_SCREENHEIGHT* 0.4));
  179. ImGui::Begin("Framebuffer");
  180. ImGui::BeginTabBar("FrameBuffer Textures");
  181. ImGui::DrawTabsBackground();
  182. if (ImGui::AddTab("Colour Buffer")) {
  183. ImTextureID texID = (void *)(intptr_t)m_FBO_texture;
  184. ImGui::Image(texID, ImVec2(DEFAULT_SCREENWIDTH*0.25, DEFAULT_SCREENHEIGHT*0.25), ImVec2(0, 1), ImVec2(1, 0));
  185. }
  186. if (ImGui::AddTab("Depth Buffer")) {
  187. ImTextureID texID = (void *)(intptr_t)m_FBO_depth_texture;
  188. ImGui::Image(texID, ImVec2(DEFAULT_SCREENWIDTH*0.25, DEFAULT_SCREENHEIGHT*0.25), ImVec2(0, 1), ImVec2(1, 0));
  189.  
  190. }
  191. ImGui::EndTabBar();
  192.  
  193.  
  194. ImGui::End();
  195.  
  196. // quit our application when escape is pressed
  197. if (glfwGetKey(m_window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  198. quit();
  199. }
  200.  
  201.  
  202. void Shadows::Draw()
  203. {
  204. // clear the backbuffer
  205. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  206.  
  207. //\===============================================================================
  208. //\ Draw the scene from the POV of the light
  209. //\===============================================================================
  210. glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
  211. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  212. glViewport(0, 0, SHADOW_BUFFER_SIZE, SHADOW_BUFFER_SIZE);
  213. DrawScene(m_shadowProgramID);
  214.  
  215. //\===============================================================================
  216. //\ Draw the scene from the regular POV of the camera
  217. //\===============================================================================
  218. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  219. glViewport(0, 0, DEFAULT_SCREENWIDTH, DEFAULT_SCREENHEIGHT);
  220. DrawScene(m_programID);
  221.  
  222. // get the view matrix from the world-space camera matrix
  223. glm::mat4 viewMatrix = glm::inverse(m_cameraMatrix);
  224. // draw the gizmos from this frame
  225. Gizmos::draw(viewMatrix, m_projectionMatrix);
  226. //\===============================================================================
  227. }
  228.  
  229. void Shadows::DrawScene(unsigned int a_programID)
  230. {
  231. //bing our shader program
  232. glUseProgram(a_programID);
  233. // get the view matrix from the world-space camera matrix
  234. glm::mat4 viewMatrix = glm::inverse(m_cameraMatrix);
  235. //bind our vertex array object
  236. glBindVertexArray(m_vao);
  237.  
  238. unsigned int shadowProjectionViewUniform = glGetUniformLocation(a_programID, "ShadowProjectionView");
  239. glUniformMatrix4fv(shadowProjectionViewUniform, 1, false, glm::value_ptr(m_shadowProjectionViewMatrix));
  240.  
  241. //get our shaders uniform location for our projectionViewMatrix and then use glUniformMatrix4fv to fill it with the correct data
  242. unsigned int projectionViewUniform = glGetUniformLocation(a_programID, "ProjectionView");
  243. glUniformMatrix4fv(projectionViewUniform, 1, false, glm::value_ptr(m_projectionMatrix * viewMatrix));
  244.  
  245. //pass throught the view matrix
  246. unsigned int viewMatrixUniform = glGetUniformLocation(a_programID, "ViewMatrix");
  247. glUniformMatrix4fv(viewMatrixUniform, 1, false, glm::value_ptr(viewMatrix));
  248.  
  249. //pass our camera position to our fragment shader uniform
  250. unsigned int cameraPosUniform = glGetUniformLocation(a_programID, "cameraPosition");
  251. glUniform4fv(cameraPosUniform, 1, glm::value_ptr(m_cameraMatrix[3]));
  252.  
  253. //pass the directional light direction to our fragment shader
  254. glm::vec4 lightDir = -m_lightPos;
  255. lightDir.w = 0.f;
  256. lightDir = glm::normalize(lightDir);
  257. unsigned int lightDirUniform = glGetUniformLocation(a_programID, "lightDirection");
  258. glUniform4fv(lightDirUniform, 1, glm::value_ptr(lightDir));
  259.  
  260. //Set the shadow texture
  261. unsigned int shadowTexUniformID = glGetUniformLocation(a_programID, "ShadowTexture");
  262. glUniform1i(shadowTexUniformID, 1);
  263. //Set our active texture, and bind our loaded texture
  264. glActiveTexture(GL_TEXTURE1);
  265. glBindTexture(GL_TEXTURE_2D, m_FBO_depth_texture);
  266.  
  267. //Draw our FBX Model
  268. // for each mesh in the model...
  269. for (unsigned int i = 0; i < m_fbxModel->getMeshCount(); ++i)
  270. {
  271. // get the current mesh
  272. FBXMeshNode *pMesh = m_fbxModel->getMeshByIndex(i);
  273.  
  274. // send the Model
  275. glm::mat4 m4Model = pMesh->m_globalTransform;// *m_modelMatrix;
  276. unsigned int modelUniform = glGetUniformLocation(a_programID, "Model");
  277. glUniformMatrix4fv(modelUniform, 1, false, glm::value_ptr(m4Model));
  278. //send the normal matrix
  279. //this is only beneficial if a model has a non-uniform scale or non-orthoganal model matrix
  280. glm::mat4 m4Normal = glm::transpose(glm::inverse(pMesh->m_globalTransform));// *m_modelMatrix;
  281. unsigned int normalMatrixUniform = glGetUniformLocation(a_programID, "NormalMatrix");
  282. glUniformMatrix4fv(normalMatrixUniform, 1, false, glm::value_ptr(m4Normal));
  283.  
  284. // Bind the texture to one of the ActiveTextures
  285. // if your shader supported multiple textures, you would bind each texture to a new Active Texture ID here
  286. //bind our textureLocation variable from the shaders and set it's value to 0 as the active texture is texture 0
  287. unsigned int texUniformID = glGetUniformLocation(a_programID, "DiffuseTexture");
  288. glUniform1i(texUniformID, 0);
  289. //set our active texture, and bind our loaded texture
  290. glActiveTexture(GL_TEXTURE0);
  291. glBindTexture(GL_TEXTURE_2D, pMesh->m_material->textureIDs[FBXMaterial::DiffuseTexture]);
  292.  
  293. // Send the vertex data to the VBO
  294. glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
  295. glBufferData(GL_ARRAY_BUFFER, pMesh->m_vertices.size() * sizeof(FBXVertex), pMesh->m_vertices.data(), GL_STATIC_DRAW);
  296.  
  297. // send the index data to the IBO
  298. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
  299. glBufferData(GL_ELEMENT_ARRAY_BUFFER, pMesh->m_indices.size() * sizeof(unsigned int), pMesh->m_indices.data(), GL_STATIC_DRAW);
  300.  
  301. glDrawElements(GL_TRIANGLES, pMesh->m_indices.size(), GL_UNSIGNED_INT, 0);
  302. }
  303. glBindVertexArray(0);
  304. glUseProgram(0);
  305. }
  306.  
  307. void Shadows::Destroy()
  308. {
  309.  
  310. m_fbxModel->unload();
  311. delete m_fbxModel;
  312.  
  313. glDeleteBuffers(1, &m_vbo);
  314. glDeleteBuffers(1, &m_ibo);
  315. glDeleteVertexArrays(1, &m_vao);
  316. glDeleteProgram(m_programID);
  317.  
  318. Gizmos::destroy();
  319. }
  320.  
  321. void Shadows::SetupFrameBuffer(unsigned int& a_fbo,
  322. unsigned int a_targetWidth,
  323. unsigned int a_targetHeight,
  324. unsigned int& a_renderTexture,
  325. unsigned int& a_depthTexture)
  326. {
  327. //\======================================================================================
  328. // Create our frame buffer object
  329. //\=====================================================================================
  330. // this would be within your onCreate() function
  331. glGenFramebuffers(1, &a_fbo);
  332.  
  333. // bind the framebuffer for editing
  334. glBindFramebuffer(GL_FRAMEBUFFER, a_fbo);
  335.  
  336. if (a_renderTexture != -1)
  337. {
  338. // create a texture to be attached to the framebuffer, stored in the derived app class as a member
  339. glGenTextures(1, &a_renderTexture);
  340.  
  341. // bind the texture for editing
  342. glBindTexture(GL_TEXTURE_2D, a_renderTexture);
  343.  
  344. // create the texture. Note, the width and height are the dimensions of the screen and the final
  345. // data pointer is 0 as we aren't including any initial data
  346. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, a_targetWidth, a_targetHeight,
  347. 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
  348.  
  349. // set the filtering if we intend to sample within a shader
  350. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  351. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  352.  
  353. glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, a_renderTexture, 0);
  354. }
  355. // m_FBO_depth would be a member for the derived application class
  356. glGenTextures(1, &a_depthTexture);
  357. glBindTexture(GL_TEXTURE_2D, a_depthTexture);
  358.  
  359. // note the use of GL_DEPTH_COMPONENT32F and GL_DEPTH_COMPONENT
  360. glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, a_targetWidth,
  361. a_targetHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
  362. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  363. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  364. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  365. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  366.  
  367. // attach it as a GL_DEPTH_ATTACHMENT
  368. // attach the texture to the 0th color attachment of the framebuffer
  369. glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, a_depthTexture, 0);
  370.  
  371. // Here we tell the framebuffer which color attachments we will be drawing to and how many
  372. if (a_renderTexture != -1)
  373. {
  374. GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
  375. glDrawBuffers(1, drawBuffers);
  376. }
  377. else
  378. {
  379. glDrawBuffer(GL_NONE);
  380. }
  381. // if Status doesn't equal GL_FRAMEBUFFER_COMPLETE there has been an error when creating it
  382. GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  383. if (status != GL_FRAMEBUFFER_COMPLETE)
  384. printf("Framebuffer Error!\n");
  385.  
  386. // binding 0 to the framebuffer slot unbinds the framebuffer and means future render calls will be sent to
  387. // the back buffer
  388. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  389.  
  390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement