| 530 | } |
| 531 | |
| 532 | void ParticleNode::render() { |
| 533 | if (_quads.empty()) { |
| 534 | Node::render(); |
| 535 | return; |
| 536 | } |
| 537 | |
| 538 | if (SharedDirector.isFrustumCulling()) { |
| 539 | const auto& firstQuad = _quads[0]; |
| 540 | auto [minX, maxX] = std::minmax({firstQuad.lt.x, firstQuad.lb.x, firstQuad.rt.x, firstQuad.rb.x}); |
| 541 | auto [minY, maxY] = std::minmax({firstQuad.lt.y, firstQuad.lb.y, firstQuad.rt.y, firstQuad.rb.y}); |
| 542 | auto [minZ, maxZ] = std::minmax({firstQuad.lt.z, firstQuad.lb.z, firstQuad.rt.z, firstQuad.rb.z}); |
| 543 | for (size_t i = 1; i < _quads.size(); i++) { |
| 544 | const auto& quad = _quads[i]; |
| 545 | std::tie(minX, maxX) = std::minmax({minX, maxX, quad.lt.x, quad.lb.x, quad.rt.x, quad.rb.x}); |
| 546 | std::tie(minY, maxY) = std::minmax({minY, maxY, quad.lt.y, quad.lb.y, quad.rt.y, quad.rb.y}); |
| 547 | std::tie(minZ, maxZ) = std::minmax({minZ, maxZ, quad.lt.z, quad.lb.z, quad.rt.z, quad.rb.z}); |
| 548 | } |
| 549 | AABB aabb{ |
| 550 | {minX, minY, minZ}, |
| 551 | {maxX, maxY, maxZ}, |
| 552 | }; |
| 553 | if (!SharedDirector.isInFrustum(aabb)) { |
| 554 | return; |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | const auto& transform = SharedDirector.getViewProjection(); |
| 559 | for (size_t i = 0; i < _quads.size(); i++) { |
| 560 | auto& quad = _quads[i]; |
| 561 | Matrix::mulVec4(&quad.lb.x, transform, quad.lb.toVec4()); |
| 562 | Matrix::mulVec4(&quad.rb.x, transform, quad.rb.toVec4()); |
| 563 | Matrix::mulVec4(&quad.lt.x, transform, quad.lt.toVec4()); |
| 564 | Matrix::mulVec4(&quad.rt.x, transform, quad.rt.toVec4()); |
| 565 | } |
| 566 | |
| 567 | BlendFunc blendFunc{_particleDef->blendFuncSource, _particleDef->blendFuncDestination}; |
| 568 | _renderState = (BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_MSAA | blendFunc.toValue()); |
| 569 | if (_flags.isOn(ParticleNode::DepthWrite)) { |
| 570 | _renderState |= (BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS); |
| 571 | } |
| 572 | SharedRendererManager.setCurrent(SharedSpriteRenderer.getTarget()); |
| 573 | SharedSpriteRenderer.push(_quads[0], _quads.size() * 4, _effect, _texture, _renderState); |
| 574 | |
| 575 | Node::render(); |
| 576 | } |
| 577 | |
| 578 | void ParticleNode::cleanup() { |
| 579 | if (_flags.isOff(Node::Cleanup)) { |
nothing calls this directly
no test coverage detected