mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-25 22:15:14 +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):
|
ColorInt(uint32_t c):
|
||||||
u32(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) {
|
static ColorInt bgra(uint32_t c) {
|
||||||
return ColorInt((c&0xff00ff00)|((c&0xff)<<16)|((c&0xff0000)>>16));
|
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 }; }
|
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:
|
// 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 bool has_uniform_color = (v0.col == v1.col && v0.col == v2.col);
|
||||||
|
|
||||||
const ImVec4 c0 = color_convert_u32_to_float4(v0.col);
|
const ColorInt c0 = ColorInt::bgra(v0.col);
|
||||||
const ImVec4 c1 = color_convert_u32_to_float4(v1.col);
|
const ColorInt c1 = ColorInt::bgra(v1.col);
|
||||||
const ImVec4 c2 = color_convert_u32_to_float4(v2.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):
|
// We often blend the same colors over and over again, so optimize for this (saves 10% total cpu):
|
||||||
uint32_t last_target_pixel = 0;
|
uint32_t last_target_pixel = 0;
|
||||||
|
@ -443,12 +464,16 @@ static void paint_triangle(const PaintTarget &target,
|
||||||
|
|
||||||
bool has_been_inside_this_row = false;
|
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) {
|
for (int x = min_x_i; x < max_x_i; ++x) {
|
||||||
const auto w0 = bary.w0;
|
const auto w0 = bary.w0;
|
||||||
const auto w1 = bary.w1;
|
const auto w1 = bary.w1;
|
||||||
const auto w2 = bary.w2;
|
const auto w2 = bary.w2;
|
||||||
bary += bary_dx;
|
bary += bary_dx;
|
||||||
|
|
||||||
|
++target_pixel;
|
||||||
|
|
||||||
{
|
{
|
||||||
// Inside/outside test:
|
// Inside/outside test:
|
||||||
const auto p = Point{ kFixedBias * x + kFixedBias / 2, kFixedBias * y + kFixedBias / 2 };
|
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;
|
has_been_inside_this_row = true;
|
||||||
|
|
||||||
uint32_t &target_pixel = target.pixels[y * target.width + x];
|
|
||||||
|
|
||||||
if (has_uniform_color && !texture) {
|
if (has_uniform_color && !texture) {
|
||||||
if (target_pixel == last_target_pixel) {
|
if (*target_pixel == last_target_pixel) {
|
||||||
target_pixel = last_output;
|
*target_pixel = last_output;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
last_target_pixel = target_pixel;
|
last_target_pixel = *target_pixel;
|
||||||
target_pixel = blend(*lastColorRef, colorRef);
|
*target_pixel = blend(*lastColorRef, colorRef);
|
||||||
last_output = target_pixel;
|
last_output = *target_pixel;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec4 src_color;
|
ColorInt src_color;
|
||||||
|
|
||||||
if (has_uniform_color) {
|
if (has_uniform_color) {
|
||||||
src_color = c0;
|
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;
|
const ImVec2 uv = w0 * v0.uv + w1 * v1.uv + w2 * v2.uv;
|
||||||
int x = uv.x * (texture->width - 1.0f) + 0.5f;
|
int x = uv.x * (texture->width - 1.0f) + 0.5f;
|
||||||
int y = uv.y * (texture->height - 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.a) { continue; }// Transparent.
|
||||||
if (src_color.w >= 1.0f) {
|
if (src_color.a == 255) {
|
||||||
// Opaque, no blending needed:
|
// Opaque, no blending needed:
|
||||||
target_pixel = color_convert_float4_to_u32(src_color);
|
*target_pixel = src_color.u32;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec4 target_color = color_convert_u32_to_float4(target_pixel);
|
const ColorInt* target_color = (const ColorInt*)target_pixel;
|
||||||
const auto blended_color = src_color.w * src_color + (1.0f - src_color.w) * target_color;
|
*target_pixel = blend(*target_color, src_color);
|
||||||
target_pixel = color_convert_float4_to_u32(blended_color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bary_current_row += bary_dy;
|
bary_current_row += bary_dy;
|
||||||
|
|
|
@ -75,7 +75,22 @@ void FurnaceGUIRenderSoftware::setBlendMode(FurnaceGUIBlendMode mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUIRenderSoftware::clear(ImVec4 color) {
|
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() {
|
bool FurnaceGUIRenderSoftware::newFrame() {
|
||||||
|
|
Loading…
Reference in a new issue