Pica/Rasterizer: Implement alpha blending.
This commit is contained in:
parent
e229ff8c83
commit
a7ae0330b1
|
@ -25,6 +25,18 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
|
|||
*(color_buffer + x + y * registers.framebuffer.GetWidth()) = value;
|
||||
}
|
||||
|
||||
static const Math::Vec4<u8> GetPixel(int x, int y) {
|
||||
u32* color_buffer_u32 = reinterpret_cast<u32*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetColorBufferPhysicalAddress())));
|
||||
|
||||
u32 value = *(color_buffer_u32 + x + y * registers.framebuffer.GetWidth());
|
||||
Math::Vec4<u8> ret;
|
||||
ret.a() = value >> 24;
|
||||
ret.r() = (value >> 16) & 0xFF;
|
||||
ret.g() = (value >> 8) & 0xFF;
|
||||
ret.b() = value & 0xFF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 GetDepth(int x, int y) {
|
||||
u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
|
||||
|
||||
|
@ -430,6 +442,78 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
|
|||
SetDepth(x >> 4, y >> 4, z);
|
||||
}
|
||||
|
||||
auto dest = GetPixel(x >> 4, y >> 4);
|
||||
|
||||
if (registers.output_merger.alphablend_enable) {
|
||||
auto params = registers.output_merger.alpha_blending;
|
||||
|
||||
auto LookupFactorRGB = [&](decltype(params)::BlendFactor factor) -> Math::Vec3<u8> {
|
||||
switch(factor) {
|
||||
case params.Zero:
|
||||
return Math::Vec3<u8>(0, 0, 0);
|
||||
|
||||
case params.One:
|
||||
return Math::Vec3<u8>(255, 255, 255);
|
||||
|
||||
case params.SourceAlpha:
|
||||
return Math::MakeVec(combiner_output.a(), combiner_output.a(), combiner_output.a());
|
||||
|
||||
case params.OneMinusSourceAlpha:
|
||||
return Math::Vec3<u8>(255-combiner_output.a(), 255-combiner_output.a(), 255-combiner_output.a());
|
||||
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unknown color blend factor %x", factor);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
auto LookupFactorA = [&](decltype(params)::BlendFactor factor) -> u8 {
|
||||
switch(factor) {
|
||||
case params.Zero:
|
||||
return 0;
|
||||
|
||||
case params.One:
|
||||
return 255;
|
||||
|
||||
case params.SourceAlpha:
|
||||
return combiner_output.a();
|
||||
|
||||
case params.OneMinusSourceAlpha:
|
||||
return 255 - combiner_output.a();
|
||||
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unknown alpha blend factor %x", factor);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
auto srcfactor = Math::MakeVec(LookupFactorRGB(params.factor_source_rgb),
|
||||
LookupFactorA(params.factor_source_a));
|
||||
auto dstfactor = Math::MakeVec(LookupFactorRGB(params.factor_dest_rgb),
|
||||
LookupFactorA(params.factor_dest_a));
|
||||
|
||||
switch (params.blend_equation_rgb) {
|
||||
case params.Add:
|
||||
{
|
||||
auto result = (combiner_output * srcfactor + dest * dstfactor) / 255;
|
||||
result.r() = std::min(255, result.r());
|
||||
result.g() = std::min(255, result.g());
|
||||
result.b() = std::min(255, result.b());
|
||||
combiner_output = result.Cast<u8>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_CRITICAL(HW_GPU, "Unknown RGB blend equation %x", params.blend_equation_rgb.Value());
|
||||
exit(0);
|
||||
}
|
||||
} else {
|
||||
LOG_CRITICAL(HW_GPU, "logic op: %x", registers.output_merger.logic_op);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
DrawPixel(x >> 4, y >> 4, combiner_output);
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue