💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1261 lines
36 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
7 years ago
6 years ago
7 years ago
7 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "render-passes.hpp"
  20. #include "ui/ui.hpp"
  21. #include <iostream>
  22. #include <limits>
  23. ClearRenderPass::ClearRenderPass():
  24. clearColor(true),
  25. clearDepth(true),
  26. clearStencil(true),
  27. color(0.0f),
  28. depth(1.0f),
  29. index(0)
  30. {}
  31. bool ClearRenderPass::load(const RenderContext* renderContext)
  32. {
  33. return true;
  34. }
  35. void ClearRenderPass::unload()
  36. {}
  37. void ClearRenderPass::render(RenderContext* renderContext)
  38. {
  39. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  40. GLbitfield mask = 0;
  41. if (clearColor)
  42. {
  43. mask |= GL_COLOR_BUFFER_BIT;
  44. glClearColor(color[0], color[1], color[2], color[3]);
  45. }
  46. if (clearDepth)
  47. {
  48. mask |= GL_DEPTH_BUFFER_BIT;
  49. glClearDepth(depth);
  50. }
  51. if (clearStencil)
  52. {
  53. mask |= GL_STENCIL_BUFFER_BIT;
  54. glClearStencil(index);
  55. }
  56. glClear(mask);
  57. }
  58. void ClearRenderPass::setClear(bool color, bool depth, bool stencil)
  59. {
  60. clearColor = color;
  61. clearDepth = depth;
  62. clearStencil = stencil;
  63. }
  64. void ClearRenderPass::setClearColor(const Vector4& color)
  65. {
  66. this->color = color;
  67. }
  68. void ClearRenderPass::setClearDepth(float depth)
  69. {
  70. this->depth = depth;
  71. }
  72. void ClearRenderPass::setClearStencil(int index)
  73. {
  74. this->index = index;
  75. }
  76. BlurRenderPass::BlurRenderPass():
  77. gammaCorrect(false)
  78. {}
  79. bool BlurRenderPass::load(const RenderContext* renderContext)
  80. {
  81. permutation = (gammaCorrect) ? 1 : 0;
  82. // Load shader source
  83. if (!shader.loadSource("data/shaders/blur.glsl"))
  84. {
  85. std::cerr << "BlurRenderPass: failed to load shader source." << std::endl;
  86. return false;
  87. }
  88. // Generate permutation
  89. if (!shader.generatePermutation(permutation))
  90. {
  91. std::cerr << "BlurRenderPass: failed to generate shader permutation." << std::endl;
  92. return false;
  93. }
  94. // Connect shader variables
  95. textureParam.connect(shader.getInput("blurTexture"));
  96. resolutionParam.connect(shader.getInput("resolution"));
  97. directionParam.connect(shader.getInput("direction"));
  98. if (!textureParam.isConnected() ||
  99. !resolutionParam.isConnected() ||
  100. !directionParam.isConnected())
  101. {
  102. std::cerr << "BlurRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  103. return false;
  104. }
  105. // Initialize shader variables
  106. resolutionParam.setValue(Vector2(renderTarget->width, renderTarget->height));
  107. const float quadVertexData[] =
  108. {
  109. -1.0f, 1.0f, 0.0f,
  110. -1.0f, -1.0f, 0.0f,
  111. 1.0f, -1.0f, 0.0f,
  112. 1.0f, 1.0f, 0.0f
  113. };
  114. const std::uint32_t quadIndexData[] =
  115. {
  116. 0, 1, 3,
  117. 3, 1, 2
  118. };
  119. quadVertexCount = 4;
  120. quadIndexCount = 6;
  121. // Create AABB geometry
  122. glGenVertexArrays(1, &quadVAO);
  123. glBindVertexArray(quadVAO);
  124. glGenBuffers(1, &quadVBO);
  125. glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
  126. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * quadVertexCount, quadVertexData, GL_STATIC_DRAW);
  127. glEnableVertexAttribArray(EMERGENT_VERTEX_POSITION);
  128. glVertexAttribPointer(EMERGENT_VERTEX_POSITION, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (char*)0 + 0*sizeof(float));
  129. glGenBuffers(1, &quadIBO);
  130. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadIBO);
  131. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * quadIndexCount, quadIndexData, GL_STATIC_DRAW);
  132. return true;
  133. }
  134. void BlurRenderPass::unload()
  135. {
  136. textureParam.disconnect();
  137. resolutionParam.disconnect();
  138. directionParam.disconnect();
  139. shader.deleteAllPermutations();
  140. glDeleteBuffers(1, &quadIBO);
  141. glDeleteBuffers(1, &quadVBO);
  142. glDeleteVertexArrays(1, &quadVAO);
  143. }
  144. void BlurRenderPass::render(RenderContext* renderContext)
  145. {
  146. // Bind framebuffer and set up viewport
  147. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  148. glViewport(0, 0, renderTarget->width, renderTarget->height);
  149. // Set up OpenGL state
  150. glDisable(GL_DEPTH_TEST);
  151. glDepthMask(GL_FALSE);
  152. glDisable(GL_BLEND);
  153. glDisable(GL_CULL_FACE);
  154. // Activate shader permutation
  155. shader.activate(permutation);
  156. // Upload shader variables to shader permutation
  157. textureParam.upload();
  158. resolutionParam.upload();
  159. directionParam.upload();
  160. // Render quad
  161. glBindVertexArray(quadVAO);
  162. glDrawElementsBaseVertex(GL_TRIANGLES, quadIndexCount, GL_UNSIGNED_INT, (void*)0, 0);
  163. // Unbind texture
  164. //glBindTexture(GL_TEXTURE_2D, 0);
  165. }
  166. ShadowMapRenderPass::ShadowMapRenderPass():
  167. croppedShadowMapViewports(nullptr),
  168. viewCamera(nullptr),
  169. splitViewFrustum(nullptr),
  170. cropMatrices(nullptr),
  171. tileMatrices(nullptr)
  172. {}
  173. bool ShadowMapRenderPass::load(const RenderContext* renderContext)
  174. {
  175. // Set maximum number of bones for skinned meshes
  176. maxBoneCount = 64;
  177. // Create split view frustum
  178. splitViewFrustum = new SplitViewFrustum(4);
  179. splitViewFrustum->setSplitSchemeWeight(0.85f);
  180. // Determine resolution of shadow maps
  181. shadowMapResolution = 4096;
  182. croppedShadowMapResolution = shadowMapResolution >> 1;
  183. // Allocate viewports
  184. croppedShadowMapViewports = new Vector4[splitViewFrustum->getSubfrustumCount()];
  185. // Setup viewports
  186. for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
  187. {
  188. int x = i % 2;
  189. int y = i / 2;
  190. Vector4* viewport = &croppedShadowMapViewports[i];
  191. (*viewport)[0] = static_cast<float>(x * croppedShadowMapResolution);
  192. (*viewport)[1] = static_cast<float>(y * croppedShadowMapResolution);
  193. (*viewport)[2] = static_cast<float>(croppedShadowMapResolution);
  194. (*viewport)[3] = static_cast<float>(croppedShadowMapResolution);
  195. }
  196. // Allocate matrices
  197. cropMatrices = new Matrix4[splitViewFrustum->getSubfrustumCount()];
  198. tileMatrices = new Matrix4[splitViewFrustum->getSubfrustumCount()];
  199. // Setup tile matrices
  200. Matrix4 tileScale = glm::scale(Vector3(0.5f, 0.5f, 1.0f));
  201. for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
  202. {
  203. float x = static_cast<float>(i % 2) * 0.5f;
  204. float y = static_cast<float>(i / 2) * 0.5f;
  205. tileMatrices[i] = glm::translate(Vector3(x, y, 0.0f)) * tileScale;
  206. }
  207. // Setup permutation values
  208. unskinnedPermutation = 0;
  209. skinnedPermutation = 1;
  210. // Load shader source
  211. if (!shader.loadSource("data/shaders/depth-pass.glsl"))
  212. {
  213. std::cerr << "ShadowMapRenderPass: failed to load shader source." << std::endl;
  214. return false;
  215. }
  216. // Generate unskinned and skinned permutations
  217. if (!shader.generatePermutation(unskinnedPermutation) || !shader.generatePermutation(skinnedPermutation))
  218. {
  219. std::cerr << "ShadowMapRenderPass: failed to generate shader permutation." << std::endl;
  220. return false;
  221. }
  222. // Allocate bone palette parameter
  223. matrixPaletteParam = new ShaderMatrix4(maxBoneCount);
  224. // Connect shader variables
  225. modelViewProjectionParam.connect(shader.getInput("modelViewProjectionMatrix"));
  226. matrixPaletteParam->connect(shader.getInput("matrixPalette"));
  227. if (!modelViewProjectionParam.isConnected() ||
  228. !matrixPaletteParam->isConnected())
  229. {
  230. std::cerr << "ShadowMapRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  231. return false;
  232. }
  233. return true;
  234. }
  235. void ShadowMapRenderPass::unload()
  236. {
  237. modelViewProjectionParam.disconnect();
  238. matrixPaletteParam->disconnect();
  239. delete matrixPaletteParam;
  240. shader.deleteAllPermutations();
  241. delete[] croppedShadowMapViewports;
  242. croppedShadowMapViewports = nullptr;
  243. delete splitViewFrustum;
  244. splitViewFrustum = nullptr;
  245. delete[] cropMatrices;
  246. cropMatrices = nullptr;
  247. delete[] tileMatrices;
  248. tileMatrices = nullptr;
  249. }
  250. void ShadowMapRenderPass::render(RenderContext* renderContext)
  251. {
  252. // Bind framebuffer and setup viewport
  253. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  254. glViewport(0, 0, renderTarget->width, renderTarget->height);
  255. // Enable depth testing
  256. glEnable(GL_DEPTH_TEST);
  257. glDepthMask(GL_TRUE);
  258. glDepthFunc(GL_LESS);
  259. // Clear the framebuffer depth
  260. glClear(GL_DEPTH_BUFFER_BIT);
  261. // Draw front and back faces
  262. glEnable(GL_CULL_FACE);
  263. glCullFace(GL_BACK);
  264. // Disable alpha blending
  265. glDisable(GL_BLEND);
  266. //const Camera& lightCamera = *(renderContext->camera);
  267. std::list<RenderOperation>* operations = renderContext->queue->getOperations();
  268. GLuint boundVAO = 0;
  269. splitViewFrustum->setMatrices(viewCamera->getView(), viewCamera->getProjection());
  270. // Sort operations
  271. operations->sort(RenderOpCompare());
  272. std::uint32_t permutation = 0xDEADBEEF;
  273. // For each frustum split
  274. for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
  275. {
  276. // Calculate crop matrix
  277. {
  278. const ViewFrustum& subfrustum = splitViewFrustum->getSubfrustum(i);
  279. // Create AABB containing the subfrustum corners
  280. AABB subfrustumBounds(subfrustum.getCorner(0), subfrustum.getCorner(0));
  281. for (std::size_t j = 1; j < 8; ++j)
  282. {
  283. subfrustumBounds.add(subfrustum.getCorner(j));
  284. }
  285. // Transform subfrustum bounds into light's clip space
  286. AABB croppingBounds = subfrustumBounds.transformed(lightCamera->getViewProjection());
  287. Vector3 cropMax = croppingBounds.getMax();
  288. Vector3 cropMin = croppingBounds.getMin();
  289. // Calculate scale
  290. Vector3 scale;
  291. scale.x = 2.0f / (cropMax.x - cropMin.x);
  292. scale.y = 2.0f / (cropMax.y - cropMin.y);
  293. scale.z = 1.0f / (cropMax.z - cropMin.z);
  294. // Quantize scale
  295. float scaleQuantizer = 64.0f;
  296. scale.x = 1.0f / std::ceil(1.0f / scale.x * scaleQuantizer) * scaleQuantizer;
  297. scale.y = 1.0f / std::ceil(1.0f / scale.y * scaleQuantizer) * scaleQuantizer;
  298. // Calculate offset
  299. Vector3 offset;
  300. offset.x = (cropMax.x + cropMin.x) * scale.x * -0.5f;
  301. offset.y = (cropMax.y + cropMin.y) * scale.y * -0.5f;
  302. offset.z = -cropMin.z * scale.z;
  303. // Quantize offset
  304. float halfTextureSize = static_cast<float>(croppedShadowMapResolution) * 0.5f;
  305. offset.x = std::ceil(offset.x * halfTextureSize) / halfTextureSize;
  306. offset.y = std::ceil(offset.y * halfTextureSize) / halfTextureSize;
  307. cropMatrices[i] = glm::translate(offset) * glm::scale(scale);
  308. }
  309. Matrix4 croppedViewProjection = cropMatrices[i] * lightCamera->getViewProjection();
  310. // Activate viewport for corresponding cropped shadow map
  311. const Vector4& viewport = croppedShadowMapViewports[i];
  312. glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
  313. // Render operations
  314. for (const RenderOperation& operation: *operations)
  315. {
  316. // Skip render operations with unsupported materials
  317. /*
  318. if (operation.material->getMaterialFormatID() != static_cast<unsigned int>(MaterialFormat::PHYSICAL))
  319. {
  320. continue;
  321. }
  322. */
  323. // Skip non shadow casters
  324. /*
  325. const PhysicalMaterial* material = static_cast<const PhysicalMaterial*>(operation.material);
  326. if (!material->shadowCaster)
  327. {
  328. continue;
  329. }
  330. */
  331. // TODO: Perform culling for subfrustums
  332. // Select permutation
  333. std::uint32_t targetPermutation = (operation.pose != nullptr) ? skinnedPermutation : unskinnedPermutation;
  334. if (permutation != targetPermutation)
  335. {
  336. permutation = targetPermutation;
  337. shader.activate(permutation);
  338. }
  339. // Pass matrix palette
  340. if (operation.pose != nullptr)
  341. {
  342. matrixPaletteParam->getConnectedInput()->upload(0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount());
  343. }
  344. const Matrix4& modelMatrix = operation.transform;
  345. Matrix4 modelViewProjectionMatrix = croppedViewProjection * modelMatrix;
  346. modelViewProjectionParam.setValue(modelViewProjectionMatrix);
  347. modelViewProjectionParam.upload();
  348. if (boundVAO != operation.vao)
  349. {
  350. glBindVertexArray(operation.vao);
  351. boundVAO = operation.vao;
  352. }
  353. glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
  354. }
  355. }
  356. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  357. }
  358. bool ShadowMapRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, const RenderOperation& opB) const
  359. {
  360. // If A is rigged
  361. if (opA.pose != nullptr)
  362. {
  363. // And B is rigged
  364. if (opB.pose != nullptr)
  365. {
  366. // Sort by VAO ID
  367. return (opA.vao <= opB.vao);
  368. }
  369. else
  370. {
  371. // Render A first
  372. return true;
  373. }
  374. }
  375. // Sort by VAO ID
  376. return (opA.vao <= opB.vao);
  377. }
  378. LightingRenderPass::LightingRenderPass():
  379. shadowMap(0),
  380. shadowCamera(nullptr),
  381. diffuseCubemap(nullptr),
  382. specularCubemap(nullptr),
  383. shadowMapPass(nullptr)
  384. {
  385. // Initialize bias matrix for calculating the model-view-projection-bias matrix (used for shadow map texture coordinate calculation)
  386. biasMatrix = glm::translate(Vector3(0.5f)) * glm::scale(Vector3(0.5f));
  387. maxBoneCount = 64;
  388. maxDirectionalLightCount = 1;
  389. maxSpotlightCount = 1;
  390. }
  391. bool LightingRenderPass::load(const RenderContext* renderContext)
  392. {
  393. // Load shaders for each material
  394. // Register parameter sets for each unique shader
  395. if (!shader.loadSource("data/shaders/standard.glsl"))
  396. {
  397. std::cerr << "LightingRenderPass: Failed to load shader source." << std::endl;
  398. return false;
  399. }
  400. /*
  401. if (renderContext != nullptr)
  402. {
  403. std::list<RenderOperation>* operations = renderContext->queue->getOperations();
  404. for (RenderOperation& op: *operations)
  405. {
  406. }
  407. }
  408. */
  409. // Set permutation values
  410. std::uint32_t IS_SKINNED = 1;
  411. std::uint32_t HAS_AMBIENT_CUBE = 1 << 7;
  412. unskinnedPermutation = HAS_AMBIENT_CUBE;
  413. skinnedPermutation = IS_SKINNED | HAS_AMBIENT_CUBE;
  414. // Generate shader permutations
  415. if (!shader.generatePermutation(unskinnedPermutation) || !shader.generatePermutation(skinnedPermutation))
  416. {
  417. std::cerr << "LightingRenderPass: failed to generate shader permutation." << std::endl;
  418. return false;
  419. }
  420. // Allocate shader array parameters
  421. parameters.matrixPalette = new ShaderMatrix4(maxBoneCount);
  422. parameters.lightViewProjectionMatrices = new ShaderMatrix4(4);
  423. // Connect shader parameters
  424. parameters.matrixPalette->connect(shader.getInput("matrixPalette"));
  425. parameters.modelMatrix.connect(shader.getInput("modelMatrix"));
  426. parameters.modelViewMatrix.connect(shader.getInput("modelViewMatrix"));
  427. parameters.modelViewProjectionMatrix.connect(shader.getInput("modelViewProjectionMatrix"));
  428. parameters.normalModelViewMatrix.connect(shader.getInput("normalModelViewMatrix"));
  429. parameters.normalModelMatrix.connect(shader.getInput("normalModelMatrix"));
  430. parameters.lightViewProjectionMatrices->connect(shader.getInput("lightViewProjectionMatrices"));
  431. parameters.splitDistances.connect(shader.getInput("splitDistances"));
  432. parameters.shadowMap.connect(shader.getInput("shadowMap"));
  433. parameters.cameraPosition.connect(shader.getInput("cameraPosition"));
  434. parameters.diffuseCubemap.connect(shader.getInput("diffuseCubemap"));
  435. parameters.specularCubemap.connect(shader.getInput("specularCubemap"));
  436. parameters.albedoOpacityMap.connect(shader.getInput("albedoOpacityMap"));
  437. parameters.metalnessRoughnessMap.connect(shader.getInput("metalnessRoughnessMap"));
  438. parameters.normalOcclusionMap.connect(shader.getInput("normalOcclusionMap"));
  439. if (!parameters.matrixPalette->isConnected() ||
  440. !parameters.modelMatrix.isConnected() ||
  441. !parameters.modelViewMatrix.isConnected() ||
  442. !parameters.modelViewProjectionMatrix.isConnected() ||
  443. !parameters.normalModelViewMatrix.isConnected() ||
  444. !parameters.normalModelMatrix.isConnected() ||
  445. !parameters.lightViewProjectionMatrices->isConnected() ||
  446. !parameters.splitDistances.isConnected() ||
  447. !parameters.shadowMap.isConnected() ||
  448. !parameters.cameraPosition.isConnected() ||
  449. !parameters.diffuseCubemap.isConnected() ||
  450. !parameters.specularCubemap.isConnected())
  451. {
  452. std::cerr << "LightingRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  453. }
  454. return true;
  455. }
  456. void LightingRenderPass::unload()
  457. {
  458. // Free shader array parameters
  459. delete parameters.matrixPalette;
  460. delete parameters.lightViewProjectionMatrices;
  461. parameters.matrixPalette = nullptr;
  462. parameters.lightViewProjectionMatrices = nullptr;
  463. shader.deleteAllPermutations();
  464. }
  465. void LightingRenderPass::render(RenderContext* renderContext)
  466. {
  467. const Camera& camera = *(renderContext->camera);
  468. std::list<RenderOperation>* operations = renderContext->queue->getOperations();
  469. // Bind framebuffer and setup viewport
  470. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  471. glViewport(0, 0, renderTarget->width, renderTarget->height);
  472. // Enable depth testing
  473. glEnable(GL_DEPTH_TEST);
  474. glDepthMask(GL_TRUE);
  475. glDepthFunc(GL_LEQUAL);
  476. // Enable backface culling
  477. glEnable(GL_CULL_FACE);
  478. glCullFace(GL_BACK);
  479. // Enable alpha blending
  480. //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  481. glDisable(GL_BLEND);
  482. Vector4 splitDistances;
  483. for (int i = 0; i < 4; ++i)
  484. {
  485. splitDistances[i] = shadowMapPass->getSplitViewFrustum().getSplitDistance(i + 1);
  486. }
  487. Vector3 directionalLightColors[3];
  488. Vector3 directionalLightDirections[3];
  489. Vector3 spotlightColors[3];
  490. Vector3 spotlightPositions[3];
  491. Vector3 spotlightAttenuations[3];
  492. Vector3 spotlightDirections[3];
  493. float spotlightCutoffs[3];
  494. float spotlightExponents[3];
  495. // Add directional light
  496. int directionalLightCount = 1;
  497. directionalLightColors[0] = Vector3(1);
  498. directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, -2, -1, 0)));
  499. // Add spotlights
  500. int spotlightCount = 0;
  501. const std::list<SceneObject*>* lights = renderContext->layer->getObjects(SceneObjectType::LIGHT);
  502. if (lights != nullptr)
  503. {
  504. for (auto object: *lights)
  505. {
  506. const Light* light = static_cast<const Light*>(object);
  507. LightType lightType = light->getLightType();
  508. if (lightType == LightType::SPOTLIGHT && light->isActive())
  509. {
  510. const Spotlight* spotlight = static_cast<const Spotlight*>(light);
  511. spotlightColors[spotlightCount] = spotlight->getScaledColor();
  512. spotlightPositions[spotlightCount] = Vector3(camera.getView() * Vector4(spotlight->getTranslation(), 1.0f));
  513. spotlightAttenuations[spotlightCount] = spotlight->getAttenuation();
  514. spotlightDirections[spotlightCount] = glm::normalize(Vector3(camera.getView() * Vector4(-spotlight->getDirection(), 0.0f)));
  515. spotlightCutoffs[spotlightCount] = spotlight->getCutoff();
  516. spotlightExponents[spotlightCount] = spotlight->getExponent();
  517. ++spotlightCount;
  518. }
  519. }
  520. }
  521. // Calculate the (light-space) view-projection matrices
  522. Matrix4 lightViewProjectionMatrices[4];
  523. for (int i = 0; i < 4; ++i)
  524. {
  525. lightViewProjectionMatrices[i] = shadowMapPass->getTileMatrix(i) * biasMatrix * shadowMapPass->getCropMatrix(i) * shadowCamera->getViewProjection();
  526. }
  527. // Set shader parameter values
  528. parameters.lightViewProjectionMatrices->setValues(0, &lightViewProjectionMatrices[0], 4);
  529. parameters.splitDistances.setValue(splitDistances);
  530. parameters.cameraPosition.setValue(camera.getTranslation());
  531. parameters.diffuseCubemap.setValue(diffuseCubemap);
  532. parameters.specularCubemap.setValue(specularCubemap);
  533. parameters.shadowMap.setValue(shadowMap);
  534. parameters.directionalLightCount.setValue(0);
  535. parameters.spotlightCount.setValue(0);
  536. std::uint32_t permutation = 0xDEADBEEF;
  537. bool blending = false;
  538. GLuint boundVAO = 0;
  539. // Sort operations
  540. //operations->sort(RenderOpCompare());
  541. // Render operations
  542. for (const RenderOperation& operation: *operations)
  543. {
  544. /*
  545. bool hasTranslucency = material->flags & (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT;
  546. if (hasTranslucency && !blending)
  547. {
  548. glEnable(GL_BLEND);
  549. blending = true;
  550. }
  551. */
  552. // Select permutation
  553. std::uint32_t targetPermutation = (operation.pose != nullptr) ? skinnedPermutation : unskinnedPermutation;
  554. if (permutation != targetPermutation)
  555. {
  556. permutation = targetPermutation;
  557. shader.activate(permutation);
  558. // Pass static params
  559. parameters.lightViewProjectionMatrices->upload();
  560. parameters.splitDistances.upload();
  561. parameters.cameraPosition.upload();
  562. parameters.diffuseCubemap.upload();
  563. parameters.specularCubemap.upload();
  564. parameters.shadowMap.upload();
  565. parameters.directionalLightCount.upload();
  566. parameters.spotlightCount.upload();
  567. /*
  568. shader->setParameter(directionalLightCountParam, directionalLightCount);
  569. shader->setParameter(directionalLightColorsParam, 0, &directionalLightColors[0], directionalLightCount);
  570. shader->setParameter(directionalLightDirectionsParam, 0, &directionalLightDirections[0], directionalLightCount);
  571. shader->setParameter(spotlightCountParam, spotlightCount);
  572. shader->setParameter(spotlightColorsParam, 0, &spotlightColors[0], spotlightCount);
  573. shader->setParameter(spotlightPositionsParam, 0, &spotlightPositions[0], spotlightCount);
  574. shader->setParameter(spotlightAttenuationsParam, 0, &spotlightAttenuations[0], spotlightCount);
  575. shader->setParameter(spotlightDirectionsParam, 0, &spotlightDirections[0], spotlightCount);
  576. shader->setParameter(spotlightCutoffsParam, 0, &spotlightCutoffs[0], spotlightCount);
  577. shader->setParameter(spotlightExponentsParam, 0, &spotlightExponents[0], spotlightCount);
  578. */
  579. }
  580. const Matrix4& modelMatrix = operation.transform;
  581. Matrix4 modelViewMatrix = camera.getView() * modelMatrix;
  582. Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix;
  583. Matrix3 normalModelViewMatrix = glm::transpose(glm::inverse(Matrix3(modelViewMatrix)));
  584. Matrix3 normalModelMatrix = glm::transpose(glm::inverse(Matrix3(modelMatrix)));
  585. parameters.modelMatrix.setValue(modelMatrix);
  586. parameters.modelViewMatrix.setValue(modelViewMatrix);
  587. parameters.modelViewProjectionMatrix.setValue(modelViewProjectionMatrix);
  588. parameters.normalModelViewMatrix.setValue(normalModelViewMatrix);
  589. parameters.normalModelMatrix.setValue(normalModelMatrix);
  590. // Upload matrix parameters
  591. parameters.modelMatrix.upload();
  592. parameters.modelViewMatrix.upload();
  593. parameters.modelViewProjectionMatrix.upload();
  594. parameters.normalModelViewMatrix.upload();
  595. parameters.normalModelMatrix.upload();
  596. // Upload pose matrix palette
  597. if (operation.pose != nullptr && parameters.matrixPalette->isConnected())
  598. {
  599. parameters.matrixPalette->getConnectedInput()->upload(0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount());
  600. }
  601. // Upload material parameters
  602. if (operation.material != nullptr)
  603. {
  604. if (operation.material->getShader() != &shader)
  605. {
  606. ((Material*)operation.material)->setShader(&shader);
  607. }
  608. operation.material->upload();
  609. }
  610. else
  611. {
  612. //std::cerr << "NULL MATERIAL!!!" << std::endl;
  613. }
  614. if (boundVAO != operation.vao)
  615. {
  616. glBindVertexArray(operation.vao);
  617. boundVAO = operation.vao;
  618. }
  619. glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
  620. }
  621. glActiveTexture(GL_TEXTURE5);
  622. glBindTexture(GL_TEXTURE_2D, 0);
  623. }
  624. bool LightingRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, const RenderOperation& opB) const
  625. {
  626. /*
  627. // Skip render operations with unsupported materials
  628. if (opA.material->getMaterialFormatID() != static_cast<unsigned int>(MaterialFormat::PHYSICAL))
  629. {
  630. return false;
  631. }
  632. else if (opB.material->getMaterialFormatID() != static_cast<unsigned int>(MaterialFormat::PHYSICAL))
  633. {
  634. return true;
  635. }
  636. // Cast materials
  637. const PhysicalMaterial* materialA = static_cast<const PhysicalMaterial*>(opA.material);
  638. const PhysicalMaterial* materialB = static_cast<const PhysicalMaterial*>(opB.material);
  639. // Determine transparency
  640. bool transparentA = materialA->flags & (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT;
  641. bool transparentB = materialB->flags & (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT;
  642. if (transparentA)
  643. {
  644. if (transparentB)
  645. {
  646. // A and B are both transparent, render back to front
  647. return (opA.depth <= opB.depth);
  648. }
  649. else
  650. {
  651. // A is transparent, B is opaque. Render B first
  652. return false;
  653. }
  654. }
  655. else
  656. {
  657. if (transparentB)
  658. {
  659. // A is opaque, B is transparent. Render A first
  660. return true;
  661. }
  662. else
  663. {
  664. // A and B are both opaque, sort by material
  665. return (opA.material < opB.material);
  666. // A and B are both opaque, render front to back
  667. //return (opA.depth > opB.depth);
  668. }
  669. }
  670. */
  671. return (opA.material->getShader() < opB.material->getShader());
  672. }
  673. DebugRenderPass::DebugRenderPass()
  674. {}
  675. bool DebugRenderPass::load(const RenderContext* renderContext)
  676. {
  677. if (!shader.loadSource("data/shaders/unlit-solid.glsl"))
  678. {
  679. std::cerr << "DebugRenderPass: Failed to load shader source." << std::endl;
  680. return false;
  681. }
  682. // Set permutation values
  683. permutation = 0;
  684. // Generate shader permutations
  685. if (!shader.generatePermutation(permutation))
  686. {
  687. std::cerr << "DebugRenderPass: failed to generate shader permutation." << std::endl;
  688. return false;
  689. }
  690. // Connect shader variables
  691. modelViewProjectionMatrixParam.connect(shader.getInput("modelViewProjectionMatrix"));
  692. if (!modelViewProjectionMatrixParam.isConnected())
  693. {
  694. std::cerr << "DebugRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  695. return false;
  696. }
  697. const float aabbVertexData[] =
  698. {
  699. -0.5, -0.5, -0.5,
  700. 0.5, -0.5, -0.5,
  701. 0.5, 0.5, -0.5,
  702. -0.5, 0.5, -0.5,
  703. -0.5, -0.5, 0.5,
  704. 0.5, -0.5, 0.5,
  705. 0.5, 0.5, 0.5,
  706. -0.5, 0.5, 0.5,
  707. };
  708. const std::uint32_t aabbIndexData[] =
  709. {
  710. 0, 1, 1, 2, 2, 3, 3, 0,
  711. 4, 5, 5, 6, 6, 7, 7, 4,
  712. 0, 4, 1, 5, 2, 6, 3, 7
  713. };
  714. aabbVertexCount = 8;
  715. aabbIndexCount = 24;
  716. // Create AABB geometry
  717. glGenVertexArrays(1, &aabbVAO);
  718. glBindVertexArray(aabbVAO);
  719. glGenBuffers(1, &aabbVBO);
  720. glBindBuffer(GL_ARRAY_BUFFER, aabbVBO);
  721. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * aabbVertexCount, aabbVertexData, GL_STATIC_DRAW);
  722. glEnableVertexAttribArray(EMERGENT_VERTEX_POSITION);
  723. glVertexAttribPointer(EMERGENT_VERTEX_POSITION, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (char*)0 + 0*sizeof(float));
  724. glGenBuffers(1, &aabbIBO);
  725. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, aabbIBO);
  726. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * aabbIndexCount, aabbIndexData, GL_STATIC_DRAW);
  727. return true;
  728. }
  729. void DebugRenderPass::unload()
  730. {
  731. modelViewProjectionMatrixParam.disconnect();
  732. shader.deleteAllPermutations();
  733. glDeleteBuffers(1, &aabbIBO);
  734. glDeleteBuffers(1, &aabbVBO);
  735. glDeleteVertexArrays(1, &aabbVAO);
  736. }
  737. void DebugRenderPass::render(RenderContext* renderContext)
  738. {
  739. // Bind framebuffer and setup viewport
  740. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  741. glViewport(0, 0, renderTarget->width, renderTarget->height);
  742. const Camera& camera = *(renderContext->camera);
  743. /*
  744. // Bind framebuffer and setup viewport
  745. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  746. glViewport(0, 0, renderTarget->width, renderTarget->height);
  747. // Clear the framebuffer depth
  748. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  749. glClearDepth(1.0);
  750. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  751. // Disable depth testing
  752. glEnable(GL_DEPTH_TEST);
  753. glDepthMask(GL_TRUE);
  754. glDepthFunc(GL_LESS);
  755. */
  756. // Disable backface culling
  757. glDisable(GL_CULL_FACE);
  758. // Disable alpha blending
  759. glDisable(GL_BLEND);
  760. // Bind unlit solid shader
  761. shader.activate(permutation);
  762. // Bind AABB geometry
  763. glBindVertexArray(aabbVAO);
  764. const std::list<SceneObject*>* objects = renderContext->layer->getObjects();
  765. for (auto object: *objects)
  766. {
  767. if (!camera.getCullingMask()->intersects(object->getBounds()))
  768. continue;
  769. const AABB& bounds = object->getBounds();
  770. const Vector3& min = bounds.getMin();
  771. const Vector3& max = bounds.getMax();
  772. Vector3 scale = max - min;
  773. Vector3 center = (min + max) * 0.5f;
  774. const Vector3& translation = center;
  775. Matrix4 modelMatrix = glm::translate(translation) * glm::scale(scale);
  776. Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix;
  777. modelViewProjectionMatrixParam.setValue(modelViewProjectionMatrix);
  778. modelViewProjectionMatrixParam.upload();
  779. glDrawElements(GL_LINES, aabbIndexCount, GL_UNSIGNED_INT, (void*)0);
  780. }
  781. }
  782. UIRenderPass::UIRenderPass()
  783. {}
  784. bool UIRenderPass::load(const RenderContext* renderContext)
  785. {
  786. if (!shader.loadSource("data/shaders/ui.glsl"))
  787. {
  788. std::cerr << "UIRenderPass: Failed to load shader source." << std::endl;
  789. return false;
  790. }
  791. // Set permutation values
  792. untexturedPermutation = 0;
  793. texturedPermutation = 1;
  794. // Generate shader permutations
  795. if (!shader.generatePermutation(untexturedPermutation) || !shader.generatePermutation(texturedPermutation))
  796. {
  797. std::cerr << "UIRenderPass: failed to generate shader permutation." << std::endl;
  798. return false;
  799. }
  800. // Connect shader variables
  801. modelViewProjectionMatrixParam.connect(shader.getInput("modelViewProjectionMatrix"));
  802. textureParam.connect(shader.getInput("tex"));
  803. textureOffsetParam.connect(shader.getInput("texcoordOffset"));
  804. textureScaleParam.connect(shader.getInput("texcoordScale"));
  805. if (!modelViewProjectionMatrixParam.isConnected() ||
  806. !textureParam.isConnected() ||
  807. !textureOffsetParam.isConnected() ||
  808. !textureScaleParam.isConnected())
  809. {
  810. std::cerr << "UIRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  811. return false;
  812. }
  813. return true;
  814. }
  815. void UIRenderPass::unload()
  816. {
  817. modelViewProjectionMatrixParam.disconnect();
  818. textureParam.disconnect();
  819. textureOffsetParam.disconnect();
  820. textureScaleParam.disconnect();
  821. shader.deleteAllPermutations();
  822. }
  823. void UIRenderPass::render(RenderContext* renderContext)
  824. {
  825. const Camera& camera = *(renderContext->camera);
  826. // Bind framebuffer and setup viewport
  827. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  828. glViewport(0, 0, renderTarget->width, renderTarget->height);
  829. // Disable depth testing
  830. glDisable(GL_DEPTH_TEST);
  831. //glDepthMask(GL_FALSE);
  832. //glDepthFunc(GL_LESS);
  833. // Disable backface culling
  834. glEnable(GL_CULL_FACE);
  835. glCullFace(GL_BACK);
  836. // Enable alpha blending
  837. glEnable(GL_BLEND);
  838. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  839. // Render operations
  840. const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
  841. for (const RenderOperation& operation: *operations)
  842. {
  843. // Skip render operations with unsupported materials
  844. /*
  845. if (operation.material->getMaterialFormatID() != static_cast<unsigned int>(MaterialFormat::UI))
  846. {
  847. continue;
  848. }
  849. */
  850. const UIMaterial* material = static_cast<const UIMaterial*>(operation.material);
  851. if (material->texture->getValue() != nullptr)
  852. {
  853. shader.activate(texturedPermutation);
  854. textureParam.setValue(material->texture->getValue());
  855. textureOffsetParam.setValue(material->textureOffset->getValue());
  856. textureScaleParam.setValue(material->textureScale->getValue());
  857. textureParam.upload();
  858. textureOffsetParam.upload();
  859. textureScaleParam.upload();
  860. }
  861. else
  862. {
  863. shader.activate(untexturedPermutation);
  864. }
  865. const Matrix4& modelMatrix = operation.transform;
  866. Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix;
  867. // Upload matrix parameters
  868. modelViewProjectionMatrixParam.setValue(modelViewProjectionMatrix);
  869. modelViewProjectionMatrixParam.upload();
  870. // Upload material parameters
  871. //operation.material->upload();
  872. // Draw geometry
  873. glBindVertexArray(operation.vao);
  874. glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
  875. }
  876. }
  877. /*
  878. VignetteRenderPass::VignetteRenderPass():
  879. shader(nullptr)
  880. {
  881. bayerTextureParam = parameterSet.addParameter("bayerTexture", ShaderParameter::Type::INT, 1);
  882. modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1);
  883. }
  884. bool VignetteRenderPass::load(const RenderContext* renderContext)
  885. {
  886. shaderLoader.undefine();
  887. shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION);
  888. shaderLoader.define("VERTEX_COLOR", EMERGENT_VERTEX_COLOR);
  889. shaderLoader.define("TEXTURE_COUNT", 1);
  890. shader = shaderLoader.load("data/shaders/vignette.glsl", &parameterSet);
  891. if (!shader)
  892. {
  893. return false;
  894. }
  895. /// @see http://www.anisopteragames.com/how-to-fix-color-banding-with-dithering/
  896. static const char pattern[] =
  897. {
  898. 0, 32, 8, 40, 2, 34, 10, 42,
  899. 48, 16, 56, 24, 50, 18, 58, 26,
  900. 12, 44, 4, 36, 14, 46, 6, 38,
  901. 60, 28, 52, 20, 62, 30, 54, 22,
  902. 3, 35, 11, 43, 1, 33, 9, 41,
  903. 51, 19, 59, 27, 49, 17, 57, 25,
  904. 15, 47, 7, 39, 13, 45, 5, 37,
  905. 63, 31, 55, 23, 61, 29, 53, 21
  906. };
  907. glGenTextures(1, &bayerTextureID);
  908. glBindTexture(GL_TEXTURE_2D, bayerTextureID);
  909. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  910. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  911. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  912. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  913. glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, pattern);
  914. return true;
  915. }
  916. void VignetteRenderPass::unload()
  917. {
  918. delete shader;
  919. shader = nullptr;
  920. glDeleteTextures(1, &bayerTextureID);
  921. }
  922. void VignetteRenderPass::render(RenderContext* renderContext)
  923. {
  924. glDisable(GL_DEPTH_TEST);
  925. glDepthMask(GL_FALSE);
  926. // Bind shader
  927. shader->bind();
  928. // Bind texture
  929. glActiveTexture(GL_TEXTURE0);
  930. glBindTexture(GL_TEXTURE_2D, bayerTextureID);
  931. // Pass texture unit to shader
  932. shader->setParameter(bayerTextureParam, 0);
  933. const Camera& camera = *(renderContext->camera);
  934. const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
  935. // Render operations
  936. for (const RenderOperation& operation: *operations)
  937. {
  938. const Material* material = operation.material;
  939. const Matrix4& modelMatrix = operation.transform;
  940. Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix;
  941. shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix);
  942. glBindVertexArray(operation.vao);
  943. glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
  944. }
  945. }
  946. */
  947. SkyboxRenderPass::SkyboxRenderPass():
  948. cubemap(nullptr)
  949. {}
  950. bool SkyboxRenderPass::load(const RenderContext* renderContext)
  951. {
  952. if (!shader.loadSource("data/shaders/skybox.glsl"))
  953. {
  954. std::cerr << "SkyboxRenderPass: Failed to load shader source." << std::endl;
  955. return false;
  956. }
  957. // Set permutation values
  958. permutation = 0;
  959. // Generate shader permutations
  960. if (!shader.generatePermutation(permutation))
  961. {
  962. std::cerr << "SkyboxRenderPass: failed to generate shader permutation." << std::endl;
  963. return false;
  964. }
  965. // Connect shader variables
  966. matrixParam.connect(shader.getInput("matrix"));
  967. cubemapParam.connect(shader.getInput("cubemap"));
  968. if (!matrixParam.isConnected() || !cubemapParam.isConnected())
  969. {
  970. std::cerr << "SkyboxRenderPass: one or more shader variables were not connected to shader inputs." << std::endl;
  971. return false;
  972. }
  973. const float quadVertexData[] =
  974. {
  975. -1.0f, 1.0f, 0.0f,
  976. -1.0f, -1.0f, 0.0f,
  977. 1.0f, -1.0f, 0.0f,
  978. 1.0f, 1.0f, 0.0f
  979. };
  980. const std::uint32_t quadIndexData[] =
  981. {
  982. 0, 1, 3,
  983. 3, 1, 2
  984. };
  985. quadVertexCount = 4;
  986. quadIndexCount = 6;
  987. // Create AABB geometry
  988. glGenVertexArrays(1, &quadVAO);
  989. glBindVertexArray(quadVAO);
  990. glGenBuffers(1, &quadVBO);
  991. glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
  992. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * quadVertexCount, quadVertexData, GL_STATIC_DRAW);
  993. glEnableVertexAttribArray(EMERGENT_VERTEX_POSITION);
  994. glVertexAttribPointer(EMERGENT_VERTEX_POSITION, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (char*)0 + 0*sizeof(float));
  995. glGenBuffers(1, &quadIBO);
  996. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadIBO);
  997. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * quadIndexCount, quadIndexData, GL_STATIC_DRAW);
  998. return true;
  999. }
  1000. void SkyboxRenderPass::unload()
  1001. {
  1002. matrixParam.disconnect();
  1003. cubemapParam.disconnect();
  1004. shader.deleteAllPermutations();
  1005. glDeleteBuffers(1, &quadIBO);
  1006. glDeleteBuffers(1, &quadVBO);
  1007. glDeleteVertexArrays(1, &quadVAO);
  1008. }
  1009. void SkyboxRenderPass::render(RenderContext* renderContext)
  1010. {
  1011. if (!cubemap)
  1012. {
  1013. return;
  1014. }
  1015. glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
  1016. glViewport(0, 0, renderTarget->width, renderTarget->height);
  1017. glDisable(GL_DEPTH_TEST);
  1018. glDepthMask(GL_FALSE);
  1019. //glDisable(GL_CULL_FACE);
  1020. //glCullFace(GL_BACK);
  1021. // Bind shader
  1022. shader.activate(permutation);
  1023. // Bind cubemap texture
  1024. cubemapParam.setValue(cubemap);
  1025. cubemapParam.upload();
  1026. // Calculate matrix
  1027. const Camera& camera = *(renderContext->camera);
  1028. Matrix4 modelView = Matrix4(Matrix3(camera.getView()));
  1029. Matrix4 matrix = glm::inverse(modelView) * glm::inverse(camera.getProjection());
  1030. // Upload matrix to shader
  1031. matrixParam.setValue(matrix);
  1032. matrixParam.upload();
  1033. // Render quad
  1034. glBindVertexArray(quadVAO);
  1035. glDrawElementsBaseVertex(GL_TRIANGLES, quadIndexCount, GL_UNSIGNED_INT, (void*)0, 0);
  1036. }