mirror of https://github.com/AxioDL/metaforce.git
aurora: Blend mode & palette fixes
More complete thermal visor rendering
This commit is contained in:
parent
ee3902db58
commit
fc742782a8
|
@ -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
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue