Sky.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //========================================================================
  2. // File: Sky.cpp - implements a sky box in D3D9 or D3D11
  3. //
  4. // Part of the GameCode4 Application
  5. //
  6. // GameCode4 is the sample application that encapsulates much of the source code
  7. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  8. // "Rez" Graham, published by Charles River Media.
  9. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  10. //
  11. // If this source code has found it's way to you, and you think it has helped you
  12. // in any way, do the authors a favor and buy a new copy of the book - there are
  13. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  14. // by clicking here:
  15. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  16. //
  17. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  18. //
  19. // The source code is managed and maintained through Google Code:
  20. // http://code.google.com/p/gamecode4/
  21. //
  22. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  23. //
  24. // This program is free software; you can redistribute it and/or
  25. // modify it under the terms of the GNU Lesser GPL v3
  26. // as published by the Free Software Foundation.
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  31. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  32. //
  33. // You should have received a copy of the GNU Lesser GPL v3
  34. // along with this program; if not, write to the Free Software
  35. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  36. //
  37. //========================================================================
  38. #include "../Unix/GameCodeStd.h"
  39. #include "Sky.h"
  40. #include "Scene.h"
  41. ////////////////////////////////////////////////////
  42. // SkyNode Implementation
  43. ////////////////////////////////////////////////////
  44. //
  45. // SkyNode::SkyNode - Chapter 16, page 554
  46. //
  47. SkyNode::SkyNode(const char *pTextureBaseName)
  48. : SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_Sky, glm::mat4(1.0f)),
  49. m_bActive(true)
  50. {
  51. m_textureBaseName = pTextureBaseName;
  52. }
  53. SkyNode::~SkyNode()
  54. {
  55. }
  56. //
  57. // SkyNode::VPreRender - Chapter 14, page 502
  58. //
  59. int SkyNode::VPreRender(Scene *pScene)
  60. {
  61. glm::vec3 cameraPos = geometry::GetPosition(m_camera->VGet()->ToWorld());
  62. glm::mat4 mat = m_Props.ToWorld();
  63. geometry::SetPosition(mat, cameraPos);
  64. VSetTransform(mat);
  65. return SceneNode::VPreRender(pScene);
  66. }
  67. OpenGLSkyNode46::OpenGLSkyNode46(const char* pTextureBaseName)
  68. : SkyNode(pTextureBaseName),
  69. m_vao(0),
  70. m_vbo(0),
  71. m_ebo(0),
  72. m_numIndices(0)
  73. {
  74. m_ShaderProgram.EnableLights(false);
  75. }
  76. OpenGLSkyNode46::~OpenGLSkyNode46()
  77. {
  78. glDeleteVertexArrays(1, &m_vao);
  79. glDeleteBuffers(1, &m_vbo);
  80. glDeleteBuffers(1, &m_ebo);
  81. }
  82. int OpenGLSkyNode46::VOnRestore(Scene *pScene)
  83. {
  84. // TODO(munnellg) - implement
  85. // TODO(munnellg) - these VOnRestore calls need to have their results checked
  86. SceneNode::VOnRestore(pScene);
  87. m_camera = pScene->GetCamera();
  88. // TODO(munnellg) - release shaders if allocating before creating shader so we don't leak memory
  89. m_ShaderProgram.OnRestore(pScene);
  90. // clear out any existing buffers
  91. glDeleteVertexArrays(1, &m_vao);
  92. glDeleteBuffers(1, &m_vbo);
  93. glDeleteBuffers(1, &m_ebo);
  94. glCreateVertexArrays(1, &m_vao);
  95. m_numVerts = 20;
  96. VertexUnlitTextured* pVertices = GCC_NEW VertexUnlitTextured[m_numVerts];
  97. GCC_ASSERT(pVertices && "Out of memory in OpenGLSkyNode46::VOnRestore");
  98. if (!pVertices)
  99. return 1;
  100. // Loop through the grid squares and calc the values
  101. // of each index. Each grid square has two triangles:
  102. //
  103. // A - B
  104. // | / |
  105. // C - D
  106. VertexUnlitTextured skyVerts[4];
  107. Color skyVertColor = g_White;
  108. float dim = 50.0f;
  109. skyVerts[0].Pos = glm::vec3( dim, dim, dim ); skyVerts[0].Uv = glm::vec2(1.0f, 0.0f);
  110. skyVerts[1].Pos = glm::vec3(-dim, dim, dim ); skyVerts[1].Uv = glm::vec2(0.0f, 0.0f);
  111. skyVerts[2].Pos = glm::vec3( dim,-dim, dim ); skyVerts[2].Uv = glm::vec2(1.0f, 1.0f);
  112. skyVerts[3].Pos = glm::vec3(-dim,-dim, dim ); skyVerts[3].Uv = glm::vec2(0.0f, 1.0f);
  113. glm::vec3 triangle[3];
  114. triangle[0] = glm::vec3(0.f,0.f,0.f);
  115. triangle[1] = glm::vec3(5.f,0.f,0.f);
  116. triangle[2] = glm::vec3(5.f,5.f,0.f);
  117. glm::vec3 edge1 = triangle[1]-triangle[0];
  118. glm::vec3 edge2 = triangle[2]-triangle[0];
  119. glm::vec3 normal;
  120. normal = glm::cross(edge1, edge2);
  121. normal = glm::normalize(normal);
  122. glm::mat4 rotY = geometry::BuildRotationY(GCC_PI/2.0f);
  123. glm::mat4 rotX = geometry::BuildRotationX(-GCC_PI/2.0f);
  124. m_sides = 5;
  125. for (int side = 0; side < m_sides; side++)
  126. {
  127. for (int v = 0; v < 4; v++)
  128. {
  129. glm::vec4 temp;
  130. if (side < m_sides-1)
  131. {
  132. temp = rotY * glm::vec4(skyVerts[v].Pos, 0.0f);
  133. }
  134. else
  135. {
  136. skyVerts[0].Uv = glm::vec2(1.0f, 1.0f);
  137. skyVerts[1].Uv = glm::vec2(1.0f, 1.0f);
  138. skyVerts[2].Uv = glm::vec2(1.0f, 1.0f);
  139. skyVerts[3].Uv = glm::vec2(1.0f, 1.0f);
  140. }
  141. skyVerts[v].Pos = glm::vec3(temp.x, temp.y, temp.z);
  142. }
  143. memcpy(&pVertices[side*4], skyVerts, sizeof(skyVerts));
  144. }
  145. glCreateBuffers(1, &m_vbo);
  146. glNamedBufferStorage(m_vbo, sizeof(VertexUnlitTextured) * m_numVerts, pVertices, 0);
  147. glVertexArrayVertexBuffer(m_vao, 0, m_vbo, 0, sizeof(VertexUnlitTextured));
  148. glEnableVertexArrayAttrib(m_vao, 0);
  149. glVertexArrayAttribFormat(m_vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
  150. glVertexArrayAttribBinding(m_vao, 0, 0);
  151. glEnableVertexArrayAttrib(m_vao, 1);
  152. glVertexArrayAttribFormat(m_vao, 1, 3, GL_FLOAT, GL_FALSE, offsetof(VertexUnlitTextured, Normal));
  153. glVertexArrayAttribBinding(m_vao, 1, 0);
  154. glEnableVertexArrayAttrib(m_vao, 2);
  155. glVertexArrayAttribFormat(m_vao, 2, 2, GL_FLOAT, GL_FALSE, offsetof(VertexUnlitTextured, Uv));
  156. glVertexArrayAttribBinding(m_vao, 2, 0);
  157. delete[] pVertices;
  158. m_numIndices = m_sides * 2 * 3;
  159. GLuint *pIndices = GCC_NEW GLuint[m_numIndices];
  160. GLuint *current = pIndices;
  161. for (int i=0; i<m_sides; i++)
  162. {
  163. // Triangle #1 ACB
  164. *(current) = GLuint(i*4);
  165. *(current + 1) = GLuint(i*4 + 2);
  166. *(current + 2) = GLuint(i*4 + 1);
  167. // Triangle #1 BCD
  168. *(current + 3) = GLuint(i*4 + 1);
  169. *(current + 4) = GLuint(i*4 + 2);
  170. *(current + 5) = GLuint(i*4 + 3);
  171. current += 6;
  172. }
  173. glCreateBuffers(1, &m_ebo);
  174. glNamedBufferStorage(m_ebo, sizeof(GLuint) * m_numIndices, pIndices, 0);
  175. glVertexArrayElementBuffer(m_vao, m_ebo);
  176. delete[] pIndices;
  177. return 0;
  178. }
  179. int OpenGLSkyNode46::VRender(Scene *pScene)
  180. {
  181. // TODO(munnellg) - implement
  182. m_ShaderProgram.SetupRender(pScene, this);
  183. // draw the skybox
  184. glBindVertexArray(m_vao);
  185. for (int side = 0; side < m_sides; side++)
  186. {
  187. // FUTURE WORK: A good optimization would be to transform the camera's
  188. // world look vector into local space, and do a dot product. If the
  189. // result is positive, we shouldn't draw the side since it has to be
  190. // behind the camera!
  191. // Sky boxes aren't culled by the normal mechanism
  192. /***
  193. // [mrmike] - This was slightly changed post press, look at the lines below this commented out code
  194. const char *suffix[] = { "_n.jpg", "_e.jpg", "_s.jpg", "_w.jpg", "_u.jpg" };
  195. name += suffix[side];
  196. ****/
  197. std::string name = GetTextureName(side);
  198. m_ShaderProgram.SetTexture(name.c_str());
  199. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *)(6 * side * sizeof(GLuint)));
  200. }
  201. glBindVertexArray(0);
  202. return 0;
  203. }
  204. std::string SkyNode::GetTextureName(const int side)
  205. {
  206. std::string name = m_textureBaseName;
  207. char *letters[] = { "n", "e", "s", "w", "u" };
  208. unsigned int index = name.find_first_of("_");
  209. GCC_ASSERT(index >=0 && index < name.length() - 1);
  210. if (index >= 0 && index < name.length() - 1)
  211. {
  212. name[index+1] = *letters[side];
  213. }
  214. return name;
  215. }