LightDirectionEmission.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "LightDirectionEmission.h"
  2. #include "LightShape.h"
  3. #include "LightSystem.h"
  4. #include <cassert>
  5. using namespace ltbl;
  6. void LightDirectionEmission::render(const sf::View &view, sf::RenderTexture &lightTempTexture, sf::RenderTexture &antumbraTempTexture, const std::vector<QuadtreeOccupant*> &shapes, sf::Shader &unshadowShader, float shadowExtension) {
  7. lightTempTexture.setView(view);
  8. lightTempTexture.clear(sf::Color::White);
  9. // Mask off light shape (over-masking - mask too much, reveal penumbra/antumbra afterwards)
  10. for (unsigned i = 0; i < shapes.size(); i++) {
  11. LightShape* pLightShape = static_cast<LightShape*>(shapes[i]);
  12. // Get boundaries
  13. std::vector<LightSystem::Penumbra> penumbras;
  14. std::vector<int> innerBoundaryIndices;
  15. std::vector<int> outerBoundaryIndices;
  16. std::vector<sf::Vector2f> innerBoundaryVectors;
  17. std::vector<sf::Vector2f> outerBoundaryVectors;
  18. LightSystem::getPenumbrasDirection(penumbras, innerBoundaryIndices, innerBoundaryVectors, outerBoundaryIndices, outerBoundaryVectors, pLightShape->_shape, _castDirection, _sourceRadius, _sourceDistance);
  19. if (innerBoundaryIndices.size() != 2 || outerBoundaryIndices.size() != 2)
  20. continue;
  21. antumbraTempTexture.clear(sf::Color::White);
  22. antumbraTempTexture.setView(view);
  23. sf::ConvexShape maskShape;
  24. float maxDist = 0.0f;
  25. for (unsigned j = 0; j < pLightShape->_shape.getPointCount(); j++)
  26. maxDist = std::max(maxDist, vectorMagnitude(view.getCenter() - pLightShape->_shape.getTransform().transformPoint(pLightShape->_shape.getPoint(j))));
  27. float totalShadowExtension = shadowExtension + maxDist;
  28. maskShape.setPointCount(4);
  29. maskShape.setPoint(0, pLightShape->_shape.getTransform().transformPoint(pLightShape->_shape.getPoint(innerBoundaryIndices[0])));
  30. maskShape.setPoint(1, pLightShape->_shape.getTransform().transformPoint(pLightShape->_shape.getPoint(innerBoundaryIndices[1])));
  31. maskShape.setPoint(2, pLightShape->_shape.getTransform().transformPoint(pLightShape->_shape.getPoint(innerBoundaryIndices[1])) + vectorNormalize(innerBoundaryVectors[1]) * totalShadowExtension);
  32. maskShape.setPoint(3, pLightShape->_shape.getTransform().transformPoint(pLightShape->_shape.getPoint(innerBoundaryIndices[0])) + vectorNormalize(innerBoundaryVectors[0]) * totalShadowExtension);
  33. maskShape.setFillColor(sf::Color::Black);
  34. antumbraTempTexture.draw(maskShape);
  35. sf::VertexArray vertexArray;
  36. vertexArray.setPrimitiveType(sf::PrimitiveType::Triangles);
  37. vertexArray.resize(3);
  38. {
  39. sf::RenderStates states;
  40. states.blendMode = sf::BlendAdd;
  41. states.shader = &unshadowShader;
  42. // Unmask with penumbras
  43. for (unsigned j = 0; j < penumbras.size(); j++) {
  44. unshadowShader.setParameter("lightBrightness", penumbras[j]._lightBrightness);
  45. unshadowShader.setParameter("darkBrightness", penumbras[j]._darkBrightness);
  46. vertexArray[0].position = penumbras[j]._source;
  47. vertexArray[1].position = penumbras[j]._source + vectorNormalize(penumbras[j]._lightEdge) * totalShadowExtension;
  48. vertexArray[2].position = penumbras[j]._source + vectorNormalize(penumbras[j]._darkEdge) * totalShadowExtension;
  49. vertexArray[0].texCoords = sf::Vector2f(0.0f, 1.0f);
  50. vertexArray[1].texCoords = sf::Vector2f(1.0f, 0.0f);
  51. vertexArray[2].texCoords = sf::Vector2f(0.0f, 0.0f);
  52. antumbraTempTexture.draw(vertexArray, states);
  53. }
  54. }
  55. antumbraTempTexture.display();
  56. // Multiply back to lightTempTexture
  57. sf::RenderStates antumbraRenderStates;
  58. antumbraRenderStates.blendMode = sf::BlendMultiply;
  59. sf::Sprite s;
  60. s.setTexture(antumbraTempTexture.getTexture());
  61. lightTempTexture.setView(lightTempTexture.getDefaultView());
  62. lightTempTexture.draw(s, antumbraRenderStates);
  63. lightTempTexture.setView(view);
  64. }
  65. for (unsigned i = 0; i < shapes.size(); i++) {
  66. LightShape* pLightShape = static_cast<LightShape*>(shapes[i]);
  67. if (pLightShape->_renderLightOverShape) {
  68. pLightShape->_shape.setFillColor(sf::Color::White);
  69. lightTempTexture.draw(pLightShape->_shape);
  70. }
  71. }
  72. // Multiplicatively blend the light over the shadows
  73. sf::RenderStates lightRenderStates;
  74. lightRenderStates.blendMode = sf::BlendMultiply;
  75. lightTempTexture.setView(lightTempTexture.getDefaultView());
  76. lightTempTexture.draw(_emissionSprite, lightRenderStates);
  77. lightTempTexture.display();
  78. }