aurora: Blend mode & palette fixes

More complete thermal visor rendering
This commit is contained in:
Luke Street 2022-07-01 00:00:29 -04:00
parent ee3902db58
commit fc742782a8
8 changed files with 65 additions and 75 deletions

View File

@ -294,7 +294,7 @@ void CModelData::RenderThermal(const zeus::CTransform& xf, const zeus::CColor& m
if (x10_animData) {
CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot);
x10_animData->SetupRender(model, nullptr, nullptr);
ThermalDraw(mulColor, addColor, flags);
ThermalDraw(model, mulColor, addColor, flags);
} else {
auto& model = PickStaticModel(EWhichModel::ThermalHot);
g_Renderer->DrawThermalModel(*model, mulColor, addColor, {}, {}, flags);
@ -444,6 +444,11 @@ void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf,
}
}
void CModelData::ThermalDraw(const zeus::CColor& mulColor, const zeus::CColor& addColor, const CModelFlags& flags) {}
void CModelData::ThermalDraw(CSkinnedModel& model, const zeus::CColor& mulColor, const zeus::CColor& addColor,
const CModelFlags& flags) {
model.DoDrawCallback([&](auto positions, auto normals) {
g_Renderer->DrawThermalModel(*model.GetModel(), mulColor, addColor, positions, normals, flags);
});
}
} // namespace metaforce

View File

@ -130,7 +130,8 @@ public:
const zeus::CColor& addColor, float t);
void DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, CTexture& tex, const zeus::CColor& addColor,
float t);
void ThermalDraw(const zeus::CColor& mulColor, const zeus::CColor& addColor, const CModelFlags& flags);
static void ThermalDraw(CSkinnedModel& model, const zeus::CColor& mulColor, const zeus::CColor& addColor,
const CModelFlags& flags);
CAnimData* GetAnimationData() { return x10_animData.get(); }
const CAnimData* GetAnimationData() const { return x10_animData.get(); }

View File

@ -222,24 +222,17 @@ void CCubeRenderer::GenerateFogVolumeRampTex() {
void CCubeRenderer::GenerateSphereRampTex() {
u8* data = x220_sphereRamp.Lock();
u32 offset = 0;
for (u32 y = 0; y < 32; ++y) {
s32 iVar3 = y >> 0x1f;
u8* row = data + offset;
for (u32 x = 0; x < 32; ++x) {
// TODO actually figure out what this is doing
const u32 vx =
((static_cast<s32>(y) >> 2) + static_cast<u32>(y < 0 && (y & 3) != 0)) * 4 + (static_cast<s32>(x) >> 3);
const u32 vy = ((iVar3 * 4 | (y * 0x40000000 + iVar3) >> 0x1e) - iVar3) * 8 + (x & 7);
const size_t height = x220_sphereRamp.GetHeight();
const size_t width = x220_sphereRamp.GetWidth();
const float halfRes = height / 2.f;
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
const zeus::CVector2f vec{
static_cast<float>(vx) / 15.5f - 1.f,
static_cast<float>(vy) / 15.5f - 1.f,
(static_cast<float>(x) - halfRes) / halfRes,
(static_cast<float>(y) - halfRes) / halfRes,
};
const auto mag = vec.magnitude();
*row = static_cast<u8>(255.f * std::clamp(-(mag * mag - 1.f), 0.f, 1.f));
++row;
data[y * height + x] = 255 - zeus::clamp(0.f, vec.canBeNormalized() ? vec.magnitude() : 0.f, 1.f) * 255;
}
offset += 32;
}
x220_sphereRamp.UnLock();
}

View File

@ -572,8 +572,8 @@ void render(wgpu::CommandEncoder& cmd) {
};
const wgpu::RenderPassDepthStencilAttachment depthStencilAttachment{
.view = gpu::g_depthBuffer.view,
.depthLoadOp = wgpu::LoadOp::Clear,
.depthStoreOp = wgpu::StoreOp::Discard,
.depthLoadOp = passInfo.clear ? wgpu::LoadOp::Clear : wgpu::LoadOp::Load,
.depthStoreOp = wgpu::StoreOp::Store,
.depthClearValue = 1.f,
};
const auto label = fmt::format(FMT_STRING("Render pass {}"), i);

View File

@ -695,7 +695,7 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
case GX::BM_NONE:
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::Src,
.srcFactor = wgpu::BlendFactor::One,
.dstFactor = wgpu::BlendFactor::Zero,
};
break;
@ -709,8 +709,8 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
case GX::BM_SUBTRACT:
colorBlendComponent = {
.operation = wgpu::BlendOperation::ReverseSubtract,
.srcFactor = wgpu::BlendFactor::Src,
.dstFactor = wgpu::BlendFactor::Dst,
.srcFactor = wgpu::BlendFactor::One,
.dstFactor = wgpu::BlendFactor::One,
};
break;
case GX::BM_LOGIC:
@ -725,7 +725,7 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
case GX::LO_COPY:
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::Src,
.srcFactor = wgpu::BlendFactor::One,
.dstFactor = wgpu::BlendFactor::Zero,
};
break;
@ -733,28 +733,7 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::Zero,
.dstFactor = wgpu::BlendFactor::Dst,
};
break;
case GX::LO_INV:
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::Zero,
.dstFactor = wgpu::BlendFactor::OneMinusDst,
};
break;
case GX::LO_INVCOPY:
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::OneMinusSrc,
.dstFactor = wgpu::BlendFactor::Zero,
};
break;
case GX::LO_SET:
colorBlendComponent = {
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::One,
.dstFactor = wgpu::BlendFactor::Zero,
.dstFactor = wgpu::BlendFactor::One,
};
break;
default:
@ -768,7 +747,7 @@ static inline wgpu::BlendState to_blend_state(GX::BlendMode mode, GX::BlendFacto
}
wgpu::BlendComponent alphaBlendComponent{
.operation = wgpu::BlendOperation::Add,
.srcFactor = wgpu::BlendFactor::SrcAlpha,
.srcFactor = wgpu::BlendFactor::One,
.dstFactor = wgpu::BlendFactor::Zero,
};
if (dstAlpha != UINT32_MAX) {

View File

@ -253,7 +253,7 @@ static inline bool is_palette_format(GX::TextureFormat fmt) {
struct TextureConfig {
GX::TextureFormat copyFmt = InvalidTextureFormat; // Underlying texture format
GX::TextureFormat loadFmt = InvalidTextureFormat; // Texture format being bound
bool renderTex = false; // Perform conversion / flip UVs
bool renderTex = false; // Perform conversion
u8 _p1 = 0;
u8 _p2 = 0;
u8 _p3 = 0;
@ -312,7 +312,7 @@ struct ShaderInfo {
std::bitset<MaxTevRegs> writesTevReg;
std::bitset<MaxTexMtx> usesTexMtx;
std::bitset<MaxPTTexMtx> usesPTTexMtx;
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes;
std::array<GX::TexGenType, MaxTexMtx> texMtxTypes{};
u32 uniformSize = 0;
bool usesFog : 1 = false;
};

View File

@ -160,8 +160,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx);
unreachable();
}
const auto swap = config.tevSwapTable[stage.tevSwapTex];
// TODO check for CH_ALPHA + config.texHasAlpha
const auto& swap = config.tevSwapTable[stage.tevSwapTex];
return fmt::format(FMT_STRING("sampled{}.{}{}{}"), stageIdx, chan_comp(swap.red), chan_comp(swap.green),
chan_comp(swap.blue));
}
@ -173,7 +172,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx);
unreachable();
}
const auto swap = config.tevSwapTable[stage.tevSwapTex];
const auto& swap = config.tevSwapTable[stage.tevSwapTex];
return fmt::format(FMT_STRING("vec3<f32>(sampled{}.{})"), stageIdx, chan_comp(swap.alpha));
}
case GX::CC_RASC: {
@ -187,7 +186,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
unreachable();
}
u32 idx = stage.channelId - GX::COLOR0A0;
const auto swap = config.tevSwapTable[stage.tevSwapRas];
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
return fmt::format(FMT_STRING("rast{}.{}{}{}"), idx, chan_comp(swap.red), chan_comp(swap.green),
chan_comp(swap.blue));
}
@ -202,7 +201,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
unreachable();
}
u32 idx = stage.channelId - GX::COLOR0A0;
const auto swap = config.tevSwapTable[stage.tevSwapRas];
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
return fmt::format(FMT_STRING("vec3<f32>(rast{}.{})"), idx, chan_comp(swap.alpha));
}
case GX::CC_ONE:
@ -371,7 +370,7 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Sha
Log.report(logvisor::Fatal, FMT_STRING("invalid texture {} for stage {}"), stage.texMapId, stageIdx);
unreachable();
}
const auto swap = config.tevSwapTable[stage.tevSwapTex];
const auto& swap = config.tevSwapTable[stage.tevSwapTex];
return fmt::format(FMT_STRING("sampled{}.{}"), stageIdx, chan_comp(swap.alpha));
}
case GX::CA_RASA: {
@ -385,7 +384,7 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Sha
unreachable();
}
u32 idx = stage.channelId - GX::COLOR0A0;
const auto swap = config.tevSwapTable[stage.tevSwapRas];
const auto& swap = config.tevSwapTable[stage.tevSwapRas];
return fmt::format(FMT_STRING("rast{}.{}"), idx, chan_comp(swap.alpha));
}
case GX::CA_KONST: {
@ -560,7 +559,7 @@ static inline std::string texture_conversion(const TextureConfig& tex, u32 stage
case GX::TF_I4:
case GX::TF_I8:
// FIXME HACK
if (tex.loadFmt != GX::TF_C4 && tex.loadFmt != GX::TF_C8 && tex.loadFmt != GX::TF_C14X2) {
if (!is_palette_format(tex.loadFmt)) {
// Perform intensity conversion
out += fmt::format(FMT_STRING("\n sampled{0} = vec4<f32>(intensityF32(sampled{0}.rgb), 0.f, 0.f, 1.f);"),
stageIdx);
@ -1076,18 +1075,29 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|| !info.sampledTextures.test(stage.texMapId)) {
continue;
}
std::string uvIn;
std::string uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), stage.texCoordId);
const auto& texConfig = config.textureConfig[stage.texMapId];
// TODO
// if (texConfig.flipUV) {
// uvIn = fmt::format(FMT_STRING("vec2<f32>(in.tex{0}_uv.x, -in.tex{0}_uv.y)"), stage.texCoordId);
// } else {
uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), stage.texCoordId);
// }
if (is_palette_format(texConfig.loadFmt)) {
std::string_view suffix;
if (!is_palette_format(texConfig.copyFmt)) {
switch (texConfig.loadFmt) {
case GX::TF_C4:
suffix = "I4"sv;
break;
// case GX::TF_C8:
// suffix = "I8";
// break;
// case GX::TF_C14X2:
// suffix = "I14X2";
// break;
default:
Log.report(logvisor::Fatal, FMT_STRING("Unsupported palette format {}"), texConfig.loadFmt);
unreachable();
}
}
fragmentFnPre +=
fmt::format(FMT_STRING("\n var sampled{0} = textureSamplePalette{3}(tex{1}, tex{1}_samp, {2}, tlut{1});"),
i, stage.texMapId, uvIn, is_palette_format(texConfig.copyFmt) ? ""sv : "RGB"sv);
i, stage.texMapId, uvIn, suffix);
} else {
fragmentFnPre += fmt::format(
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{1}, tex{1}_samp, {2}, ubuf.tex{1}_lod);"), i,
@ -1233,8 +1243,8 @@ fn intensityF32(rgb: vec3<f32>) -> f32 {{
// https://github.com/dolphin-emu/dolphin/blob/4cd48e609c507e65b95bca5afb416b59eaf7f683/Source/Core/VideoCommon/TextureConverterShaderGen.cpp#L237-L241
return dot(rgb, vec3(0.257, 0.504, 0.098)) + 16.0 / 255.0;
}}
fn intensityI32(rgb: vec3<f32>) -> i32 {{
return i32(dot(rgb, vec3(0.257, 0.504, 0.098)) * 255.f);
fn intensityI4(rgb: vec3<f32>) -> i32 {{
return i32(intensityF32(rgb) * 16.f);
}}
fn textureSamplePalette(tex: texture_2d<i32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{
// Gather index values
@ -1250,16 +1260,16 @@ fn textureSamplePalette(tex: texture_2d<i32>, samp: sampler, uv: vec2<f32>, tlut
var t1 = mix(c0, c1, f.x);
return mix(t0, t1, f.y);
}}
fn textureSamplePaletteRGB(tex: texture_2d<f32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{
fn textureSamplePaletteI4(tex: texture_2d<f32>, samp: sampler, uv: vec2<f32>, tlut: texture_2d<f32>) -> vec4<f32> {{
// Gather RGB channels
var iR = textureGather(0, tex, samp, uv);
var iG = textureGather(1, tex, samp, uv);
var iB = textureGather(2, tex, samp, uv);
// Perform intensity conversion
var i0 = intensityI32(vec3<f32>(iR[0], iG[0], iB[0]));
var i1 = intensityI32(vec3<f32>(iR[1], iG[1], iB[1]));
var i2 = intensityI32(vec3<f32>(iR[2], iG[2], iB[2]));
var i3 = intensityI32(vec3<f32>(iR[3], iG[3], iB[3]));
var i0 = intensityI4(vec3<f32>(iR[0], iG[0], iB[0]));
var i1 = intensityI4(vec3<f32>(iR[1], iG[1], iB[1]));
var i2 = intensityI4(vec3<f32>(iR[2], iG[2], iB[2]));
var i3 = intensityI4(vec3<f32>(iR[3], iG[3], iB[3]));
// Load palette colors
var c0 = textureLoad(tlut, vec2<i32>(i0, 0), 0);
var c1 = textureLoad(tlut, vec2<i32>(i1, 0), 0);

View File

@ -75,13 +75,15 @@ TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mi
.texture = ref.texture,
.mipLevel = mip,
};
const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks);
// const auto range = push_texture_data(data.data() + offset, dataSize, bytesPerRow, heightBlocks);
const auto dataLayout = wgpu::TextureDataLayout{
.offset = range.offset,
// .offset = range.offset,
.bytesPerRow = bytesPerRow,
.rowsPerImage = heightBlocks,
};
g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize);
// TODO
// g_textureUploads.emplace_back(dataLayout, std::move(dstView), physicalSize);
g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize);
offset += dataSize;
}
if (data.size() != UINT32_MAX && offset < data.size()) {