diff --git a/interfaces/Crafter.Graphics-Rendertarget.cppm b/interfaces/Crafter.Graphics-Rendertarget.cppm index 4dabef1..5084c37 100644 --- a/interfaces/Crafter.Graphics-Rendertarget.cppm +++ b/interfaces/Crafter.Graphics-Rendertarget.cppm @@ -78,25 +78,69 @@ export namespace Crafter { } break; } + case OpaqueType::SemiOpaque: case OpaqueType::Transparent: - // For transparent, always perform blending - for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) { - std::uint16_t src_y = y - element->scaled.position.y; - for (std::uint16_t x = dirty.left; x < dirty.right; x++) { - std::uint16_t src_x = x - element->scaled.position.x; - Vector src = src_buffer[src_y * src_width + src_x]; - Vector dst = buffer[frame][y * this->sizeX + x]; - - float srcA = src.a / 255.0f; - float dstA = dst.a / 255.0f;k + if constexpr(std::same_as) { + for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) { + std::uint16_t src_y = y - element->scaled.position.y; + std::uint16_t rowSize = dirty.right - dirty.left; + constexpr std::uint8_t elementsPerVector = VectorF16L<1, 1, 1>::MaxSize/VectorF16L<1, 1, 1>::MaxElement; + while(rowSize > 0) { + if(rowSize < elementsPerVector) { + for(; rowSize > 0; rowSize--) { + std::uint16_t src_x = rowSize - element->scaled.position.x; + Vector src = src_buffer[src_y * src_width + src_x]; + Vector dst = buffer[frame][y * this->sizeX + rowSize]; - float outA = srcA + dstA * (1.0f - srcA); - this->buffer[frame][y * this->sizeX + x] = Vector( - static_cast((src.r + dst.r * (1.0f - srcA)) / outA), - static_cast((src.g + dst.g * (1.0f - srcA)) / outA), - static_cast((src.b + dst.b * (1.0f - srcA)) / outA), - static_cast(outA * 255) - ); + _Float16 outA = src.a + dst.a * (1.0f - src.a); + this->buffer[frame][y * this->sizeX + rowSize] = Vector( + static_cast((src.r + dst.r * (1.0f - src.a)) / outA), + static_cast((src.g + dst.g * (1.0f - src.a)) / outA), + static_cast((src.b + dst.b * (1.0f - src.a)) / outA), + static_cast(outA * 255) + ); + } + break; + } else { + std::uint16_t src_x = rowSize - element->scaled.position.x; + using VectorType = VectorF16L<4, VectorF16L<1, 1, 1>::MaxElement / 4, VectorF16L<1, 1, 1>::MaxSize/((VectorF16L<1, 1, 1>::MaxElement / 4)*4)>; + VectorType src(src_buffer[src_y * src_width + src_x].v); + VectorType dst(buffer[frame][y * this->sizeX + rowSize].v); + + VectorType srcA = src.ShufflePacked<3,3,3,3>(); + VectorType dstA = dst.ShufflePacked<3,3,3,3>(); + + VectorType srcANeg = -srcA; + + VectorType outA = VectorType::MulitplyAdd(dstA, srcANeg, srcA); + + VectorType result = src + dst * srcANeg / outA; + result = VectorType::BlendPacked<0,0,0,1>(dst, outA); + result.Store(buffer[frame][y * this->sizeX + rowSize].v); + + rowSize -= elementsPerVector; + } + } + } + } else { + for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) { + std::uint16_t src_y = y - element->scaled.position.y; + for (std::uint16_t x = dirty.left; x < dirty.right; x++) { + std::uint16_t src_x = x - element->scaled.position.x; + Vector src = src_buffer[src_y * src_width + src_x]; + Vector dst = buffer[frame][y * this->sizeX + x]; + + float srcA = src.a / 255.0f; + float dstA = dst.a / 255.0f; + + float outA = srcA + dstA * (1.0f - srcA); + this->buffer[frame][y * this->sizeX + x] = Vector( + static_cast((src.r + dst.r * (1.0f - srcA)) / outA), + static_cast((src.g + dst.g * (1.0f - srcA)) / outA), + static_cast((src.b + dst.b * (1.0f - srcA)) / outA), + static_cast(outA * 255) + ); + } } } break; @@ -121,6 +165,10 @@ export namespace Crafter { clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::int32_t(0)), std::min(element->oldScale[frame].position.x + element->oldScale[frame].size.x, this->sizeX), std::max(element->oldScale[frame].position.y, std::int32_t(0)), std::min(element->oldScale[frame].position.y + element->oldScale[frame].size.y, this->sizeY)); element->oldScale[frame] = element->scaled; element->redraw[frame] = false; + } else if(element->redraw[frame]) { + clipRects.emplace_back(std::max(element->scaled.position.x, std::int32_t(0)), std::min(element->scaled.position.x + element->scaled.size.x, this->sizeX), std::max(element->scaled.position.y, std::int32_t(0)), std::min(element->scaled.position.y + element->scaled.size.y, this->sizeY)); + element->oldScale[frame] = element->scaled; + element->redraw[frame] = false; } } for(Transform2D* child : elementTransform->children) {