💿🐜 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.

1248 lines
36 KiB

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