rendering update

This commit is contained in:
Jorijn van der Graaf 2026-03-22 21:08:02 +01:00
commit 7fdab4f62b
4 changed files with 33 additions and 49 deletions

View file

@ -115,5 +115,16 @@ export namespace Crafter {
redraw[i] = true; redraw[i] = true;
} }
} }
void CopyNearestNeighbor(Vector<std::uint8_t, 4>* dst, std::uint16_t dstSizeX, std::uint16_t dstScaledSizeX, std::uint16_t dstScaledSizeY, std::uint16_t offsetX, std::uint16_t offsetY) {
for (std::uint16_t y = 0; y < dstScaledSizeY; y++) {
std::uint16_t srcY = y * scaled.size.y / dstScaledSizeY;
std::uint16_t dstY = y + offsetY;
for (std::uint16_t x = 0; x < dstScaledSizeX; x++) {
std::uint16_t srcX = x * scaled.size.x / dstScaledSizeX;
std::uint16_t dstX = x + offsetX;
dst[dstY * dstSizeX + dstX] = buffer[srcY * this->scaled.size.x + srcX];
}
}
}
}; };
} }

View file

@ -31,10 +31,10 @@ export namespace Crafter {
std::vector<std::tuple<const Transform*, std::uint32_t, std::uint32_t, std::chrono::nanoseconds>> renderTimings; std::vector<std::tuple<const Transform*, std::uint32_t, std::uint32_t, std::chrono::nanoseconds>> renderTimings;
#endif #endif
Transform2D transform; Transform2D transform;
std::int32_t sizeX; std::uint16_t sizeX;
std::int32_t sizeY; std::uint16_t sizeY;
RendertargetBase() = default; RendertargetBase() = default;
RendertargetBase(std::int16_t sizeX, std::int16_t sizeY) : sizeX(sizeX), sizeY(sizeY), transform({0, 0, 1, 1, 0, 0, 0}){ RendertargetBase(std::uint16_t sizeX, std::uint16_t sizeY) : sizeX(sizeX), sizeY(sizeY), transform({0, 0, 1, 1, 0, 0, 0}){
transform.scaled.size.x = sizeX; transform.scaled.size.x = sizeX;
transform.scaled.size.y = sizeY; transform.scaled.size.y = sizeY;
transform.scaled.position.x = 0; transform.scaled.position.x = 0;
@ -71,56 +71,30 @@ export namespace Crafter {
std::int32_t src_height = element->scaled.size.y; std::int32_t src_height = element->scaled.size.y;
switch (element->opaque) { switch (element->opaque) {
case OpaqueType::FullyOpaque: case OpaqueType::FullyOpaque: {
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) { for (std::int32_t y = dirty.top; y < dirty.bottom; y++) {
std::int32_t src_y = y - element->scaled.position.y; std::int32_t src_y = y - element->scaled.position.y;
std::memcpy(&this->buffer[frame][y * this->sizeX], &src_buffer[src_y * src_width], dirty.right-dirty.left*sizeof(Vector<T, Channels, Alignment>));
for (std::int32_t x = dirty.left; x < dirty.right; x++) {
std::int32_t src_x = x - element->scaled.position.x;
this->buffer[frame][y * this->sizeX + x] = src_buffer[src_y * src_width + src_x];
}
} }
break; break;
case OpaqueType::SemiOpaque:
// For semi-opaque, we can avoid blending when alpha is 0 or 255
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) {
std::int32_t src_y = y - element->scaled.position.y;
for (std::int32_t x = dirty.left; x < dirty.right; x++) {
std::int32_t src_x = x - element->scaled.position.x;
Vector<std::uint8_t, 4> src_pixel = src_buffer[src_y * src_width + src_x];
if (src_pixel.a == 0) {
continue;
} }
this->buffer[frame][y * this->sizeX + x] = src_pixel;
}
}
break;
case OpaqueType::Transparent: case OpaqueType::Transparent:
// For transparent, always perform blending // For transparent, always perform blending
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) { for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
std::int32_t src_y = y - element->scaled.position.y; std::uint16_t src_y = y - element->scaled.position.y;
for (std::int32_t x = dirty.left; x < dirty.right; x++) { for (std::uint16_t x = dirty.left; x < dirty.right; x++) {
std::int32_t src_x = x - element->scaled.position.x; std::uint16_t src_x = x - element->scaled.position.x;
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x]; Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + x]; Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + x];
if(src.a == 0) {
continue;
}
float srcA = src.a / 255.0f; float srcA = src.a / 255.0f;
float dstA = dst.a / 255.0f; float dstA = dst.a / 255.0f;k
float outA = srcA + dstA * (1.0f - srcA); float outA = srcA + dstA * (1.0f - srcA);
this->buffer[frame][y * this->sizeX + x] = Vector<T, Channels, Alignment>( this->buffer[frame][y * this->sizeX + x] = Vector<T, Channels, Alignment>(
static_cast<T>((src.r * srcA + dst.r * dstA * (1.0f - srcA)) / outA), static_cast<T>((src.r + dst.r * (1.0f - srcA)) / outA),
static_cast<T>((src.g * srcA + dst.g * dstA * (1.0f - srcA)) / outA), static_cast<T>((src.g + dst.g * (1.0f - srcA)) / outA),
static_cast<T>((src.b * srcA + dst.b * dstA * (1.0f - srcA)) / outA), static_cast<T>((src.b + dst.b * (1.0f - srcA)) / outA),
static_cast<T>(outA * 255) static_cast<T>(outA * 255)
); );
} }

View file

@ -30,10 +30,10 @@ export namespace Crafter {
float height; float height;
float offsetX; float offsetX;
float offsetY; float offsetY;
std::int32_t z; std::uint8_t z;
bool maintainAspectRatio; bool maintainAspectRatio;
Anchor2D() = default; Anchor2D() = default;
Anchor2D(float x, float y, float width, float height, float offsetX, float offsetY, std::int32_t z, bool maintainAspectRatio = false); Anchor2D(float x, float y, float width, float height, float offsetX, float offsetY, std::uint8_t z, bool maintainAspectRatio = false);
}; };
struct Transform2D { struct Transform2D {
@ -73,7 +73,6 @@ export namespace Crafter {
scaled.size.y = anchor.height * parent.scaled.size.x; scaled.size.y = anchor.height * parent.scaled.size.x;
} }
} else { } else {
scaled.size.x = anchor.width * parent.scaled.size.x; scaled.size.x = anchor.width * parent.scaled.size.x;
scaled.size.y = anchor.height * parent.scaled.size.y; scaled.size.y = anchor.height * parent.scaled.size.y;
} }

View file

@ -33,15 +33,15 @@ export namespace Crafter {
}; };
struct ScaleData2D { struct ScaleData2D {
Vector<std::int32_t, 2> position; Vector<std::uint16_t, 2> position;
Vector<std::int32_t, 2> size; Vector<std::uint16_t, 2> size;
}; };
struct ClipRect { struct ClipRect {
std::int32_t left; std::uint16_t left;
std::int32_t right; std::uint16_t right;
std::int32_t top; std::uint16_t top;
std::int32_t bottom; std::uint16_t bottom;
}; };
struct FrameTime { struct FrameTime {