vulkan2d fixes
This commit is contained in:
parent
1c1a142f52
commit
ea18f32300
4 changed files with 279 additions and 36 deletions
|
|
@ -38,9 +38,9 @@ void main()
|
||||||
|
|
||||||
for (uint16_t i = 1us; i < UITransformBuffer[bufferStart].count+1; i++) {
|
for (uint16_t i = 1us; i < UITransformBuffer[bufferStart].count+1; i++) {
|
||||||
if(pixel.x > UITransformBuffer[bufferStart].data[i].x && pixel.x < UITransformBuffer[bufferStart].data[i].x + UITransformBuffer[bufferStart].data[i].sizeX && pixel.y > UITransformBuffer[bufferStart].data[i].y && pixel.y < UITransformBuffer[bufferStart].data[i].y + UITransformBuffer[bufferStart].data[i].sizeY) {
|
if(pixel.x > UITransformBuffer[bufferStart].data[i].x && pixel.x < UITransformBuffer[bufferStart].data[i].x + UITransformBuffer[bufferStart].data[i].sizeX && pixel.y > UITransformBuffer[bufferStart].data[i].y && pixel.y < UITransformBuffer[bufferStart].data[i].y + UITransformBuffer[bufferStart].data[i].sizeY) {
|
||||||
int16_t srcX = int16_t((pixel.x - UITransformBuffer[bufferStart].data[i].x) * UITransformBuffer[bufferStart].data[i].bufferX / UITransformBuffer[bufferStart].data[i].sizeX);
|
int16_t srcX = int16_t(float(pixel.x - UITransformBuffer[bufferStart].data[i].x) * float(UITransformBuffer[bufferStart].data[i].bufferX) / float(UITransformBuffer[bufferStart].data[i].sizeX));
|
||||||
int16_t srcY = int16_t((pixel.y - UITransformBuffer[bufferStart].data[i].y) * UITransformBuffer[bufferStart].data[i].bufferY / UITransformBuffer[bufferStart].data[i].sizeY);
|
int16_t srcY = int16_t(float(pixel.y - UITransformBuffer[bufferStart].data[i].y) * float(UITransformBuffer[bufferStart].data[i].bufferY) / float(UITransformBuffer[bufferStart].data[i].sizeY));
|
||||||
hitValue = vec4(UIPixelBuffer[bufferStart + UITransformBuffer[bufferStart].count].pixels[srcY * UITransformBuffer[bufferStart].data[i].bufferX + srcX]);
|
hitValue = vec4(UIPixelBuffer[bufferStart + 1].pixels[srcY * UITransformBuffer[bufferStart].data[i].bufferX + srcX]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,17 +53,23 @@ RendertargetVulkan::RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendertargetVulkan::UpdateBuffer(std::uint8_t frame) {
|
void RendertargetVulkan::UpdateElements() {
|
||||||
elements.clear();
|
elements.clear();
|
||||||
|
std::sort(transform->children.begin(), transform->children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; });
|
||||||
for(Transform2D* child : transform.children) {
|
for(Transform2D* child : transform.children) {
|
||||||
SetOrderResursive(child);
|
SetOrderResursive(child);
|
||||||
}
|
}
|
||||||
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
||||||
|
elements[i]->ScaleElement(transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RendertargetVulkan::UpdateBuffer(std::uint8_t frame) {
|
||||||
transformBuffer[frame].Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, elements.size()+1);
|
transformBuffer[frame].Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, elements.size()+1);
|
||||||
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
||||||
std::uint16_t* sizePtr = reinterpret_cast<std::uint16_t*>(transformBuffer[frame].value);
|
std::uint16_t* sizePtr = reinterpret_cast<std::uint16_t*>(transformBuffer[frame].value);
|
||||||
*sizePtr = static_cast<std::uint16_t>(elements.size());
|
*sizePtr = static_cast<std::uint16_t>(elements.size());
|
||||||
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
||||||
elements[i]->ScaleElement(transform);
|
|
||||||
val[i].scaled = elements[i]->scaled;
|
val[i].scaled = elements[i]->scaled;
|
||||||
val[i].bufferX = elements[i]->bufferX;
|
val[i].bufferX = elements[i]->bufferX;
|
||||||
val[i].bufferY = elements[i]->bufferY;
|
val[i].bufferY = elements[i]->bufferY;
|
||||||
|
|
@ -73,10 +79,6 @@ void RendertargetVulkan::UpdateBuffer(std::uint8_t frame) {
|
||||||
|
|
||||||
void RendertargetVulkan::ReorderBuffer(std::uint8_t frame) {
|
void RendertargetVulkan::ReorderBuffer(std::uint8_t frame) {
|
||||||
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(transformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
||||||
elements.clear();
|
|
||||||
for(Transform2D* child : transform.children) {
|
|
||||||
SetOrderResursive(child);
|
|
||||||
}
|
|
||||||
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
for(std::uint16_t i = 0; i < elements.size(); i++) {
|
||||||
val[i].scaled = elements[i]->scaled;
|
val[i].scaled = elements[i]->scaled;
|
||||||
val[i].bufferX = elements[i]->bufferX;
|
val[i].bufferX = elements[i]->bufferX;
|
||||||
|
|
@ -147,13 +149,13 @@ void RendertargetVulkan::WriteDescriptors(std::span<VkResourceDescriptorInfoEXT>
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendertargetVulkan::SetOrderResursive(Transform2D* elementTransform) {
|
void RendertargetVulkan::SetOrderResursive(Transform2D* elementTransform) {
|
||||||
std::sort(elementTransform->children.begin(), elementTransform->children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; });
|
RenderingElement2DVulkanBase* renderer = dynamic_cast<RenderingElement2DVulkanBase*>(elementTransform);
|
||||||
for(Transform2D* childTransform : elementTransform->children) {
|
|
||||||
RenderingElement2DVulkanBase* renderer = dynamic_cast<RenderingElement2DVulkanBase*>(childTransform);
|
|
||||||
if(renderer) {
|
if(renderer) {
|
||||||
renderer->index = elements.size();
|
renderer->index = elements.size();
|
||||||
elements.push_back(renderer);
|
elements.push_back(renderer);
|
||||||
}
|
}
|
||||||
|
std::sort(elementTransform->children.begin(), elementTransform->children.end(), [](Transform2D* a, Transform2D* b){ return a->anchor.z < b->anchor.z; });
|
||||||
|
for(Transform2D* childTransform : elementTransform->children) {
|
||||||
SetOrderResursive(childTransform);
|
SetOrderResursive(childTransform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import :VulkanBuffer;
|
||||||
import :Types;
|
import :Types;
|
||||||
import :Window;
|
import :Window;
|
||||||
import :DescriptorHeapVulkan;
|
import :DescriptorHeapVulkan;
|
||||||
|
import :Font;
|
||||||
|
|
||||||
export namespace Crafter {
|
export namespace Crafter {
|
||||||
struct RenderingElement2DVulkanBase : Transform2D {
|
struct RenderingElement2DVulkanBase : Transform2D {
|
||||||
|
|
@ -51,28 +52,44 @@ export namespace Crafter {
|
||||||
|
|
||||||
template<bool Owning, bool Mapped>
|
template<bool Owning, bool Mapped>
|
||||||
struct RenderingElement2DVulkan : RenderingElement2DVulkanBase {
|
struct RenderingElement2DVulkan : RenderingElement2DVulkanBase {
|
||||||
RenderingElement2DVulkan(Anchor2D anchor, RendertargetBase& target, Transform2D& parent) requires(Owning) : RenderingElement2DVulkanBase(anchor) {
|
RenderingElement2DVulkan(Anchor2D anchor, RendertargetBase& target, Transform2D& parent, bool single = false) requires(Owning) : RenderingElement2DVulkanBase(anchor) {
|
||||||
GetScale(target, parent);
|
GetScale(target, parent);
|
||||||
this->bufferX = this->scaled.size.x;
|
this->bufferX = this->scaled.size.x;
|
||||||
this->bufferY = this->scaled.size.y;
|
this->bufferY = this->scaled.size.y;
|
||||||
|
if(single) {
|
||||||
|
buffers[0] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||||
|
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
||||||
|
buffers[i] = buffers[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||||
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
||||||
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) requires(Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY) {
|
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, bool single = false) requires(Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY) {
|
||||||
|
if(single) {
|
||||||
|
buffers[0] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||||
|
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
||||||
|
buffers[i] = buffers[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||||
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
||||||
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, std::array<VulkanBufferBase*, Window::numFrames>&& buffers) requires(!Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY, std::move(buffers)) {
|
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, std::array<VulkanBufferBase*, Window::numFrames>&& buffers) requires(!Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY, std::move(buffers)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderingElement2DVulkan(Anchor2D anchor, const std::filesystem::path& assetPath, bool single) requires(Owning && Mapped) : RenderingElement2DVulkanBase(anchor) {
|
RenderingElement2DVulkan(Anchor2D anchor, const std::filesystem::path& assetPath, bool single = false) requires(Owning && Mapped) : RenderingElement2DVulkanBase(anchor) {
|
||||||
TextureAssetInfo info = TextureAsset<_Float16>::LoadInfo(assetPath);
|
TextureAssetInfo info = TextureAsset<_Float16>::LoadInfo(assetPath);
|
||||||
this->bufferX = info.sizeX;
|
this->bufferX = info.sizeX;
|
||||||
this->bufferY = info.sizeY;
|
this->bufferY = info.sizeY;
|
||||||
|
|
@ -82,13 +99,13 @@ export namespace Crafter {
|
||||||
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
||||||
buffers[i] = buffers[0];
|
buffers[i] = buffers[0];
|
||||||
}
|
}
|
||||||
TextureAsset<_Float16>::Load(assetPath, reinterpret_cast<_Float16*>(static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value), this->bufferX, this->bufferY);
|
TextureAsset<Vector<_Float16, 4, 4>>::Load(assetPath, static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value, this->bufferX, this->bufferY);
|
||||||
} else {
|
} else {
|
||||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||||
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>();
|
||||||
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||||
}
|
}
|
||||||
TextureAsset<_Float16>::Load(assetPath, reinterpret_cast<_Float16*>(static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value), this->bufferX, this->bufferY);
|
TextureAsset<Vector<_Float16, 4, 4>>::Load(assetPath, static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value, this->bufferX, this->bufferY);
|
||||||
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
for(std::uint8_t i = 1; i < Window::numFrames; i++) {
|
||||||
std::memcpy(static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->value, static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value, this->bufferX * this->bufferY * sizeof(_Float16));
|
std::memcpy(static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[i])->value, static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped>*>(buffers[0])->value, this->bufferX * this->bufferY * sizeof(_Float16));
|
||||||
}
|
}
|
||||||
|
|
@ -122,6 +139,229 @@ export namespace Crafter {
|
||||||
child->UpdatePosition(window, *this);
|
child->UpdatePosition(window, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int utf8_decode(const char* s, int* bytes_consumed) {
|
||||||
|
unsigned char c = s[0];
|
||||||
|
if (c < 0x80) {
|
||||||
|
*bytes_consumed = 1;
|
||||||
|
return c;
|
||||||
|
} else if ((c & 0xE0) == 0xC0) {
|
||||||
|
*bytes_consumed = 2;
|
||||||
|
return ((c & 0x1F) << 6) | (s[1] & 0x3F);
|
||||||
|
} else if ((c & 0xF0) == 0xE0) {
|
||||||
|
*bytes_consumed = 3;
|
||||||
|
return ((c & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F);
|
||||||
|
} else if ((c & 0xF8) == 0xF0) {
|
||||||
|
*bytes_consumed = 4;
|
||||||
|
return ((c & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[2] & 0x3F) << 6) | (s[3] & 0x3F);
|
||||||
|
}
|
||||||
|
*bytes_consumed = 1;
|
||||||
|
return 0xFFFD; // replacement char
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderText(std::span<const std::string_view> lines, float size, Vector<_Float16, 4> color, Font& font, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) requires(Mapped) {
|
||||||
|
float scale = stbtt_ScaleForPixelHeight(&font.font, size);
|
||||||
|
int baseline = (int)(font.ascent * scale);
|
||||||
|
std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
|
||||||
|
std::uint32_t currentY = baseline;
|
||||||
|
for(std::string_view line : lines) {
|
||||||
|
|
||||||
|
std::uint32_t lineWidth = 0;
|
||||||
|
for (const char c : line) {
|
||||||
|
int advance, lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&font.font, c, &advance, &lsb);
|
||||||
|
lineWidth += (int)(advance * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t x = 0;
|
||||||
|
switch (alignment) {
|
||||||
|
case TextAlignment::Left:
|
||||||
|
x = 0;
|
||||||
|
break;
|
||||||
|
case TextAlignment::Center:
|
||||||
|
x = (this->scaled.size.x - lineWidth) / 2;
|
||||||
|
break;
|
||||||
|
case TextAlignment::Right:
|
||||||
|
x = this->scaled.size.x - lineWidth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* p = line.data();
|
||||||
|
const char* end = p + line.size();
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
int bytes;
|
||||||
|
int codepoint = utf8_decode(p, &bytes);
|
||||||
|
p += bytes;
|
||||||
|
|
||||||
|
int ax;
|
||||||
|
int lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&font.font, codepoint, &ax, &lsb);
|
||||||
|
|
||||||
|
int c_x1, c_y1, c_x2, c_y2;
|
||||||
|
stbtt_GetCodepointBitmapBox(&font.font, codepoint, scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);
|
||||||
|
|
||||||
|
int w = c_x2 - c_x1;
|
||||||
|
int h = c_y2 - c_y1;
|
||||||
|
|
||||||
|
std::vector<unsigned char> bitmap(w * h);
|
||||||
|
stbtt_MakeCodepointBitmap(&font.font, bitmap.data(), w, h, w, scale, scale, codepoint);
|
||||||
|
|
||||||
|
// Only render characters that fit within the scaled bounds
|
||||||
|
switch(opaque) {
|
||||||
|
case OpaqueType::FullyOpaque: {
|
||||||
|
for (int j = 0; j < h; j++) {
|
||||||
|
for (int i = 0; i < w; i++) {
|
||||||
|
int bufferX = x + i + c_x1 + offsetX;
|
||||||
|
int bufferY = currentY + j + c_y1 + offsetY;
|
||||||
|
|
||||||
|
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
|
||||||
|
for(std::uint8_t frame = 0; frame < Window::numFrames; frame++) {
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX] = {color.r, color.g, color.b, static_cast<_Float16>(bitmap[j * w + i])};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpaqueType::SemiOpaque:
|
||||||
|
case OpaqueType::Transparent: {
|
||||||
|
for (int j = 0; j < h; j++) {
|
||||||
|
for (int i = 0; i < w; i++) {
|
||||||
|
int bufferX = x + i + c_x1 + offsetX;
|
||||||
|
int bufferY = currentY + j + c_y1 + offsetY;
|
||||||
|
|
||||||
|
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
|
||||||
|
std::uint8_t alpha = bitmap[j * w + i];
|
||||||
|
_Float16 srcA = (_Float16(alpha)/_Float16(255.0f))*color.a;
|
||||||
|
for(std::uint8_t frame = 0; frame < Window::numFrames; frame++) {
|
||||||
|
Vector<_Float16, 4, 4> dst = static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX];
|
||||||
|
|
||||||
|
_Float16 outA = srcA + dst.a * (1.0f - srcA);
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX] = Vector<_Float16, 4, 4>(
|
||||||
|
(color.r * srcA + dst.r * dst.a * (1.0f - srcA)),
|
||||||
|
(color.g * srcA + dst.g * dst.a * (1.0f - srcA)),
|
||||||
|
(color.b * srcA + dst.b * dst.a * (1.0f - srcA)),
|
||||||
|
outA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += (int)(ax * scale);
|
||||||
|
|
||||||
|
if (p + 1 < end) {
|
||||||
|
int next;
|
||||||
|
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentY += lineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderText(std::span<const std::string_view> lines, float size, Vector<_Float16, 4> color, Font& font, std::uint8_t frame, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) requires(Mapped) {
|
||||||
|
float scale = stbtt_ScaleForPixelHeight(&font.font, size);
|
||||||
|
int baseline = (int)(font.ascent * scale);
|
||||||
|
std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
|
||||||
|
std::uint32_t currentY = baseline;
|
||||||
|
for(std::string_view line : lines) {
|
||||||
|
|
||||||
|
std::uint32_t lineWidth = 0;
|
||||||
|
for (const char c : line) {
|
||||||
|
int advance, lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&font.font, c, &advance, &lsb);
|
||||||
|
lineWidth += (int)(advance * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t x = 0;
|
||||||
|
switch (alignment) {
|
||||||
|
case TextAlignment::Left:
|
||||||
|
x = 0;
|
||||||
|
break;
|
||||||
|
case TextAlignment::Center:
|
||||||
|
x = (this->scaled.size.x - lineWidth) / 2;
|
||||||
|
break;
|
||||||
|
case TextAlignment::Right:
|
||||||
|
x = this->scaled.size.x - lineWidth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* p = line.data();
|
||||||
|
const char* end = p + line.size();
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
int bytes;
|
||||||
|
int codepoint = utf8_decode(p, &bytes);
|
||||||
|
p += bytes;
|
||||||
|
|
||||||
|
int ax;
|
||||||
|
int lsb;
|
||||||
|
stbtt_GetCodepointHMetrics(&font.font, codepoint, &ax, &lsb);
|
||||||
|
|
||||||
|
int c_x1, c_y1, c_x2, c_y2;
|
||||||
|
stbtt_GetCodepointBitmapBox(&font.font, codepoint, scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);
|
||||||
|
|
||||||
|
int w = c_x2 - c_x1;
|
||||||
|
int h = c_y2 - c_y1;
|
||||||
|
|
||||||
|
std::vector<unsigned char> bitmap(w * h);
|
||||||
|
stbtt_MakeCodepointBitmap(&font.font, bitmap.data(), w, h, w, scale, scale, codepoint);
|
||||||
|
|
||||||
|
// Only render characters that fit within the scaled bounds
|
||||||
|
switch(opaque) {
|
||||||
|
case OpaqueType::FullyOpaque: {
|
||||||
|
for (int j = 0; j < h; j++) {
|
||||||
|
for (int i = 0; i < w; i++) {
|
||||||
|
int bufferX = x + i + c_x1 + offsetX;
|
||||||
|
int bufferY = currentY + j + c_y1 + offsetY;
|
||||||
|
|
||||||
|
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX] = {color.r, color.g, color.b, static_cast<_Float16>(bitmap[j * w + i])};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpaqueType::SemiOpaque:
|
||||||
|
case OpaqueType::Transparent: {
|
||||||
|
for (int j = 0; j < h; j++) {
|
||||||
|
for (int i = 0; i < w; i++) {
|
||||||
|
int bufferX = x + i + c_x1 + offsetX;
|
||||||
|
int bufferY = currentY + j + c_y1 + offsetY;
|
||||||
|
|
||||||
|
if (bufferX >= 0 && bufferX < (int)this->bufferX && bufferY >= 0 && bufferY < (int)this->bufferY) {
|
||||||
|
std::uint8_t alpha = bitmap[j * w + i];
|
||||||
|
_Float16 srcA = (_Float16(alpha)/_Float16(255.0f))*color.a;
|
||||||
|
Vector<_Float16, 4, 4> dst = static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX];
|
||||||
|
|
||||||
|
_Float16 outA = srcA + dst.a * (1.0f - srcA);
|
||||||
|
static_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(buffers[frame])->value[bufferY * this->bufferX + bufferX] = Vector<_Float16, 4, 4>(
|
||||||
|
(color.r * srcA + dst.r * dst.a * (1.0f - srcA)),
|
||||||
|
(color.g * srcA + dst.g * dst.a * (1.0f - srcA)),
|
||||||
|
(color.b * srcA + dst.b * dst.a * (1.0f - srcA)),
|
||||||
|
outA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += (int)(ax * scale);
|
||||||
|
|
||||||
|
if (p + 1 < end) {
|
||||||
|
int next;
|
||||||
|
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentY += lineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -71,6 +71,7 @@ export namespace Crafter {
|
||||||
RendertargetVulkan() = default;
|
RendertargetVulkan() = default;
|
||||||
RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY, std::vector<RenderingElement2DVulkanBase*>&& elements);
|
RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY, std::vector<RenderingElement2DVulkanBase*>&& elements);
|
||||||
RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY);
|
RendertargetVulkan(std::uint16_t sizeX, std::uint16_t sizeY);
|
||||||
|
void UpdateElements();
|
||||||
void UpdateBuffer(std::uint8_t frame);
|
void UpdateBuffer(std::uint8_t frame);
|
||||||
void ReorderBuffer(std::uint8_t frame);
|
void ReorderBuffer(std::uint8_t frame);
|
||||||
void WriteDescriptors(std::span<VkResourceDescriptorInfoEXT> infos, std::span<VkHostAddressRangeEXT> ranges, std::uint16_t start, std::uint32_t bufferOffset, DescriptorHeapVulkan& descriptorHeap);
|
void WriteDescriptors(std::span<VkResourceDescriptorInfoEXT> infos, std::span<VkHostAddressRangeEXT> ranges, std::uint16_t start, std::uint32_t bufferOffset, DescriptorHeapVulkan& descriptorHeap);
|
||||||
|
|
@ -183,16 +184,16 @@ export namespace Crafter {
|
||||||
void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>& clipRects) {
|
void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>& clipRects) {
|
||||||
RenderingElement2DBase<T, Frames>* element = dynamic_cast<RenderingElement2DBase<T, Frames>*>(elementTransform);
|
RenderingElement2DBase<T, Frames>* element = dynamic_cast<RenderingElement2DBase<T, Frames>*>(elementTransform);
|
||||||
if(element) {
|
if(element) {
|
||||||
// if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) {
|
if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) {
|
||||||
// clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
clipRects.emplace_back(std::max(element->scaled.position.x, std::int16_t(0)), std::min(std::int16_t(element->scaled.position.x + element->scaled.size.x), std::int16_t(this->sizeX)), std::max(element->scaled.position.y, std::int16_t(0)), std::min(std::int16_t(element->scaled.position.y + element->scaled.size.y), std::int16_t(this->sizeY)));
|
||||||
// clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.x + element->oldScale[frame].size.x), this->sizeX), std::max(element->oldScale[frame].position.y, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.y + element->oldScale[frame].size.y), this->sizeY));
|
clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::int16_t(0)), std::min(std::int16_t(element->oldScale[frame].position.x + element->oldScale[frame].size.x), std::int16_t(this->sizeX)), std::max(element->oldScale[frame].position.y, std::int16_t(0)), std::min(std::int16_t(element->oldScale[frame].position.y + element->oldScale[frame].size.y), std::int16_t(this->sizeY)));
|
||||||
// element->oldScale[frame] = element->scaled;
|
element->oldScale[frame] = element->scaled;
|
||||||
// element->redraw[frame] = false;
|
element->redraw[frame] = false;
|
||||||
// } else if(element->redraw[frame]) {
|
} else if(element->redraw[frame]) {
|
||||||
// clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
clipRects.emplace_back(std::max(element->scaled.position.x, std::int16_t(0)), std::min(std::int16_t(element->scaled.position.x + element->scaled.size.x), std::int16_t(this->sizeX)), std::max(element->scaled.position.y, std::int16_t(0)), std::min(std::int16_t(element->scaled.position.y + element->scaled.size.y), std::int16_t(this->sizeY)));
|
||||||
// element->oldScale[frame] = element->scaled;
|
element->oldScale[frame] = element->scaled;
|
||||||
// element->redraw[frame] = false;
|
element->redraw[frame] = false;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
for(Transform2D* child : elementTransform->children) {
|
for(Transform2D* child : elementTransform->children) {
|
||||||
AddOldRects(child, frame, clipRects);
|
AddOldRects(child, frame, clipRects);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue