mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-29 07:53:01 +00:00
software renderer, part G
This commit is contained in:
parent
b7e909d1d8
commit
44b6ec15e9
2 changed files with 56 additions and 18 deletions
57
extern/imgui_software_renderer/imgui_sw.cpp
vendored
57
extern/imgui_software_renderer/imgui_sw.cpp
vendored
|
@ -59,6 +59,12 @@ union ColorInt
|
|||
ColorInt(uint32_t c):
|
||||
u32(c) {}
|
||||
|
||||
ColorInt(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha):
|
||||
b(blue),
|
||||
g(green),
|
||||
r(red),
|
||||
a(alpha) {}
|
||||
|
||||
static ColorInt bgra(uint32_t c) {
|
||||
return ColorInt((c&0xff00ff00)|((c&0xff)<<16)|((c&0xff0000)>>16));
|
||||
}
|
||||
|
@ -119,6 +125,21 @@ bool operator!=(const ImVec2 &a, const ImVec2 &b) { return a.x != b.x || a.y !=
|
|||
|
||||
ImVec4 operator*(const float f, const ImVec4 &v) { return ImVec4{ f * v.x, f * v.y, f * v.z, f * v.w }; }
|
||||
|
||||
|
||||
ColorInt operator*(const float other, const ColorInt& that)
|
||||
{
|
||||
return ColorInt(
|
||||
(that.r * (int)(other * 256.0f)) >> 8,
|
||||
(that.g * (int)(other * 256.0f)) >> 8,
|
||||
(that.b * (int)(other * 256.0f)) >> 8,
|
||||
(that.a * (int)(other * 256.0f)) >> 8
|
||||
);
|
||||
}
|
||||
|
||||
ColorInt operator+(const ColorInt& l, const ColorInt& r) {
|
||||
return ColorInt(l.u32+r.u32);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copies of functions in ImGui, inlined for speed:
|
||||
|
||||
|
@ -428,9 +449,9 @@ static void paint_triangle(const PaintTarget &target,
|
|||
|
||||
const bool has_uniform_color = (v0.col == v1.col && v0.col == v2.col);
|
||||
|
||||
const ImVec4 c0 = color_convert_u32_to_float4(v0.col);
|
||||
const ImVec4 c1 = color_convert_u32_to_float4(v1.col);
|
||||
const ImVec4 c2 = color_convert_u32_to_float4(v2.col);
|
||||
const ColorInt c0 = ColorInt::bgra(v0.col);
|
||||
const ColorInt c1 = ColorInt::bgra(v1.col);
|
||||
const ColorInt c2 = ColorInt::bgra(v2.col);
|
||||
|
||||
// We often blend the same colors over and over again, so optimize for this (saves 10% total cpu):
|
||||
uint32_t last_target_pixel = 0;
|
||||
|
@ -443,12 +464,16 @@ static void paint_triangle(const PaintTarget &target,
|
|||
|
||||
bool has_been_inside_this_row = false;
|
||||
|
||||
uint32_t* target_pixel = &target.pixels[y * target.width + min_x_i - 1];
|
||||
|
||||
for (int x = min_x_i; x < max_x_i; ++x) {
|
||||
const auto w0 = bary.w0;
|
||||
const auto w1 = bary.w1;
|
||||
const auto w2 = bary.w2;
|
||||
bary += bary_dx;
|
||||
|
||||
++target_pixel;
|
||||
|
||||
{
|
||||
// Inside/outside test:
|
||||
const auto p = Point{ kFixedBias * x + kFixedBias / 2, kFixedBias * y + kFixedBias / 2 };
|
||||
|
@ -465,20 +490,19 @@ static void paint_triangle(const PaintTarget &target,
|
|||
}
|
||||
has_been_inside_this_row = true;
|
||||
|
||||
uint32_t &target_pixel = target.pixels[y * target.width + x];
|
||||
|
||||
if (has_uniform_color && !texture) {
|
||||
if (target_pixel == last_target_pixel) {
|
||||
target_pixel = last_output;
|
||||
if (*target_pixel == last_target_pixel) {
|
||||
*target_pixel = last_output;
|
||||
continue;
|
||||
}
|
||||
last_target_pixel = target_pixel;
|
||||
target_pixel = blend(*lastColorRef, colorRef);
|
||||
last_output = target_pixel;
|
||||
last_target_pixel = *target_pixel;
|
||||
*target_pixel = blend(*lastColorRef, colorRef);
|
||||
last_output = *target_pixel;
|
||||
continue;
|
||||
}
|
||||
|
||||
ImVec4 src_color;
|
||||
ColorInt src_color;
|
||||
|
||||
if (has_uniform_color) {
|
||||
src_color = c0;
|
||||
|
@ -492,19 +516,18 @@ static void paint_triangle(const PaintTarget &target,
|
|||
const ImVec2 uv = w0 * v0.uv + w1 * v1.uv + w2 * v2.uv;
|
||||
int x = uv.x * (texture->width - 1.0f) + 0.5f;
|
||||
int y = uv.y * (texture->height - 1.0f) + 0.5f;
|
||||
src_color.w *= sample_font_texture(*texture, x, y) / 255.0f;
|
||||
src_color.a = (src_color.a * sample_font_texture(*texture, x, y) + 255) >> 8;
|
||||
}
|
||||
|
||||
if (src_color.w <= 0.0f) { continue; }// Transparent.
|
||||
if (src_color.w >= 1.0f) {
|
||||
if (!src_color.a) { continue; }// Transparent.
|
||||
if (src_color.a == 255) {
|
||||
// Opaque, no blending needed:
|
||||
target_pixel = color_convert_float4_to_u32(src_color);
|
||||
*target_pixel = src_color.u32;
|
||||
continue;
|
||||
}
|
||||
|
||||
ImVec4 target_color = color_convert_u32_to_float4(target_pixel);
|
||||
const auto blended_color = src_color.w * src_color + (1.0f - src_color.w) * target_color;
|
||||
target_pixel = color_convert_float4_to_u32(blended_color);
|
||||
const ColorInt* target_color = (const ColorInt*)target_pixel;
|
||||
*target_pixel = blend(*target_color, src_color);
|
||||
}
|
||||
|
||||
bary_current_row += bary_dy;
|
||||
|
|
|
@ -75,7 +75,22 @@ void FurnaceGUIRenderSoftware::setBlendMode(FurnaceGUIBlendMode mode) {
|
|||
}
|
||||
|
||||
void FurnaceGUIRenderSoftware::clear(ImVec4 color) {
|
||||
// TODO
|
||||
SDL_Surface* surf=SDL_GetWindowSurface(sdlWin);
|
||||
if (!surf) return;
|
||||
ImU32 clearToWhat=ImGui::ColorConvertFloat4ToU32(color);
|
||||
clearToWhat=(clearToWhat&0xff00ff00)|((clearToWhat&0xff)<<16)|((clearToWhat&0xff0000)>>16);
|
||||
|
||||
bool mustLock=SDL_MUSTLOCK(surf);
|
||||
if (mustLock) {
|
||||
if (SDL_LockSurface(surf)!=0) return;
|
||||
}
|
||||
unsigned int* pixels=(unsigned int*)surf->pixels;
|
||||
for (size_t total=surf->w*surf->h; total; total--) {
|
||||
*(pixels++)=clearToWhat;
|
||||
}
|
||||
if (mustLock) {
|
||||
SDL_UnlockSurface(surf);
|
||||
}
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderSoftware::newFrame() {
|
||||
|
|
Loading…
Reference in a new issue