mirror of https://github.com/AxioDL/metaforce.git
aurora: Continue lights implementation
This commit is contained in:
parent
724deee2ab
commit
59cf0255bf
|
@ -70,7 +70,7 @@ struct ClipRect {
|
|||
struct Light {
|
||||
zeus::CVector3f pos{0.f, 0.f, 0.f};
|
||||
zeus::CVector3f dir{0.f, 0.f, -1.f};
|
||||
zeus::CColor color{0.f, 0.f, 0.f, 0.f};
|
||||
zeus::CColor color{0.f, 1.f};
|
||||
zeus::CVector3f linAtt{1.f, 0.f, 0.f};
|
||||
zeus::CVector3f angAtt{1.f, 0.f, 0.f};
|
||||
};
|
||||
|
@ -89,10 +89,6 @@ struct ScopedDebugGroup {
|
|||
void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHandle& tex, float lod) noexcept;
|
||||
void unbind_texture(GX::TexMapID id) noexcept;
|
||||
|
||||
// TODO migrate to GX
|
||||
void load_light(GX::LightID id, const Light& light) noexcept;
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept;
|
||||
|
||||
void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept;
|
||||
void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept;
|
||||
|
||||
|
|
|
@ -92,19 +92,13 @@ void GXSetChanCtrl(GX::ChannelID id, bool lightingEnabled, GX::ColorSrc ambSrc,
|
|||
Log.report(logvisor::Fatal, FMT_STRING("bad channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
if (diffFn != GX::DF_NONE && diffFn != GX::DF_CLAMP) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled diffuse fn {}"), diffFn);
|
||||
unreachable();
|
||||
}
|
||||
if (attnFn != GX::AF_NONE && attnFn != GX::AF_SPOT) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled attn fn {}"), attnFn);
|
||||
unreachable();
|
||||
}
|
||||
u32 idx = id - GX::COLOR0A0;
|
||||
auto& chan = g_gxState.colorChannelConfig[idx];
|
||||
chan.lightingEnabled = lightingEnabled;
|
||||
chan.ambSrc = ambSrc;
|
||||
chan.matSrc = matSrc;
|
||||
chan.diffFn = diffFn;
|
||||
chan.attnFn = attnFn;
|
||||
g_gxState.colorChannelState[idx].lightState = lightState;
|
||||
}
|
||||
void GXSetAlphaCompare(GX::Compare comp0, u8 ref0, GX::AlphaOp op, GX::Compare comp1, u8 ref1) noexcept {
|
||||
|
@ -361,37 +355,7 @@ void GXInitSpecularDirHA(GX::LightObj* light, float nx, float ny, float nz, floa
|
|||
void GXInitLightColor(GX::LightObj* light, GX::Color col) { light->color = col; }
|
||||
|
||||
void GXLoadLightObjImm(const GX::LightObj* light, GX::LightID id) {
|
||||
u32 idx = 0;
|
||||
switch (id) {
|
||||
case GX::LIGHT0:
|
||||
idx = 0;
|
||||
break;
|
||||
case GX::LIGHT1:
|
||||
idx = 1;
|
||||
break;
|
||||
case GX::LIGHT2:
|
||||
idx = 2;
|
||||
break;
|
||||
case GX::LIGHT3:
|
||||
idx = 3;
|
||||
break;
|
||||
case GX::LIGHT4:
|
||||
idx = 4;
|
||||
break;
|
||||
case GX::LIGHT5:
|
||||
idx = 5;
|
||||
break;
|
||||
case GX::LIGHT6:
|
||||
idx = 6;
|
||||
break;
|
||||
case GX::LIGHT7:
|
||||
idx = 7;
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 idx = std::log2<u32>(id);
|
||||
aurora::gfx::Light realLight;
|
||||
realLight.pos.assign(light->px, light->py, light->pz);
|
||||
realLight.dir.assign(light->nx, light->ny, light->nz);
|
||||
|
@ -442,11 +406,6 @@ void bind_texture(GX::TexMapID id, metaforce::EClampMode clamp, const TextureHan
|
|||
}
|
||||
void unbind_texture(GX::TexMapID id) noexcept { gx::g_gxState.textures[static_cast<size_t>(id)].reset(); }
|
||||
|
||||
void load_light(GX::LightID id, const Light& light) noexcept { gx::g_gxState.lights[std::log2<u32>(id)] = light; }
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept {
|
||||
gx::g_gxState.lights[std::log2<u32>(id)] = ambient;
|
||||
}
|
||||
|
||||
namespace gx {
|
||||
using gpu::g_device;
|
||||
using gpu::g_graphicsConfig;
|
||||
|
@ -829,27 +788,21 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
|||
buf.append(&g_gxState.colorChannelState[i].matColor, 16);
|
||||
|
||||
if (g_gxState.colorChannelConfig[i].lightingEnabled) {
|
||||
zeus::CColor ambient = zeus::skClear;
|
||||
int addedLights = 0;
|
||||
const auto& lightState = g_gxState.colorChannelState[i].lightState;
|
||||
for (int li = 0; li < lightState.size(); ++li) {
|
||||
if (!lightState.test(li)) {
|
||||
continue;
|
||||
}
|
||||
const auto& variant = g_gxState.lights[li];
|
||||
if (std::holds_alternative<zeus::CColor>(variant)) {
|
||||
ambient += std::get<zeus::CColor>(variant);
|
||||
} else if (std::holds_alternative<Light>(variant)) {
|
||||
const auto& light = g_gxState.lights[li];
|
||||
static_assert(sizeof(Light) == 80);
|
||||
buf.append(&std::get<Light>(variant), sizeof(Light));
|
||||
buf.append(&light, sizeof(Light));
|
||||
++addedLights;
|
||||
}
|
||||
}
|
||||
constexpr Light emptyLight{};
|
||||
for (int li = addedLights; li < GX::MaxLights; ++li) {
|
||||
buf.append(&emptyLight, sizeof(Light));
|
||||
}
|
||||
buf.append(&ambient, 16);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
|
|
|
@ -75,6 +75,8 @@ struct TextureBind {
|
|||
struct ColorChannelConfig {
|
||||
GX::ColorSrc matSrc = GX::SRC_REG;
|
||||
GX::ColorSrc ambSrc = GX::SRC_REG;
|
||||
GX::DiffuseFn diffFn = GX::DF_NONE;
|
||||
GX::AttnFn attnFn = GX::AF_NONE;
|
||||
bool lightingEnabled = false;
|
||||
u8 _p1 = 0;
|
||||
u8 _p2 = 0;
|
||||
|
@ -149,7 +151,7 @@ struct GXState {
|
|||
std::array<zeus::CColor, GX::MAX_KCOLOR> kcolors;
|
||||
std::array<ColorChannelConfig, MaxColorChannels> colorChannelConfig;
|
||||
std::array<ColorChannelState, MaxColorChannels> colorChannelState;
|
||||
std::array<LightVariant, GX::MaxLights> lights;
|
||||
std::array<Light, GX::MaxLights> lights;
|
||||
std::array<TevStage, MaxTevStages> tevStages;
|
||||
std::array<TextureBind, MaxTextures> textures;
|
||||
std::array<TexMtxVariant, MaxTexMtx> texMtxs;
|
||||
|
|
|
@ -548,7 +548,7 @@ ShaderInfo build_shader_info(const ShaderConfig& config) noexcept {
|
|||
if (info.sampledColorChannels.test(i)) {
|
||||
info.uniformSize += 32;
|
||||
if (config.colorChannels[i].lightingEnabled) {
|
||||
info.uniformSize += (80 * GX::MaxLights) + 16;
|
||||
info.uniformSize += (80 * GX::MaxLights);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +758,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
"\n out.pos = ubuf.proj * vec4<f32>(mv_pos, 1.0);"),
|
||||
vtx_attr(config, GX::VA_POS), vtx_attr(config, GX::VA_NRM));
|
||||
if constexpr (EnableNormalVisualization) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), vtxOutIdx++);
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>,"), vtxOutIdx++);
|
||||
vtxXfrAttrsPre += "\n out.nrm = mv_nrm;";
|
||||
}
|
||||
|
||||
|
@ -825,7 +825,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
}
|
||||
for (int i = 0; i < info.usesTevReg.size(); ++i) {
|
||||
if (info.usesTevReg.test(i)) {
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>,"), i);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i);
|
||||
}
|
||||
}
|
||||
|
@ -835,51 +835,77 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
continue;
|
||||
}
|
||||
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_amb: vec4<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_amb: vec4<f32>,"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>,"), i);
|
||||
|
||||
if (config.colorChannels[i].lightingEnabled) {
|
||||
const auto& cc = config.colorChannels[i];
|
||||
if (cc.lightingEnabled) {
|
||||
if (!addedLightStruct) {
|
||||
uniformPre +=
|
||||
"\n"
|
||||
"struct Light {\n"
|
||||
" pos: vec3<f32>;\n"
|
||||
" dir: vec3<f32>;\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" lin_att: vec3<f32>;\n"
|
||||
" ang_att: vec3<f32>;\n"
|
||||
" pos: vec3<f32>,\n"
|
||||
" dir: vec3<f32>,\n"
|
||||
" color: vec4<f32>,\n"
|
||||
" lin_att: vec3<f32>,\n"
|
||||
" ang_att: vec3<f32>,\n"
|
||||
"};";
|
||||
addedLightStruct = true;
|
||||
}
|
||||
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>;"), i, GX::MaxLights);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lighting_ambient{}: vec4<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>,"), i, GX::MaxLights);
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>,"), vtxOutIdx++, i);
|
||||
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), vtxOutIdx++, i);
|
||||
std::string ambSrc, matSrc, lightAttnFn, lightDiffFn;
|
||||
if (cc.ambSrc == GX::SRC_VTX) {
|
||||
ambSrc = vtx_attr(config, static_cast<GX::Attr>(GX::VA_CLR0 + i));
|
||||
} else if (cc.ambSrc == GX::SRC_REG) {
|
||||
ambSrc = fmt::format(FMT_STRING("ubuf.cc{0}_amb"), i);
|
||||
}
|
||||
if (cc.matSrc == GX::SRC_VTX) {
|
||||
matSrc = vtx_attr(config, static_cast<GX::Attr>(GX::VA_CLR0 + i));
|
||||
} else if (cc.matSrc == GX::SRC_REG) {
|
||||
matSrc = fmt::format(FMT_STRING("ubuf.cc{0}_mat"), i);
|
||||
}
|
||||
GX::DiffuseFn diffFn = cc.diffFn;
|
||||
if (cc.attnFn == GX::AF_NONE) {
|
||||
lightAttnFn = "attn = 1.0;";
|
||||
} else if (cc.attnFn == GX::AF_SPOT) {
|
||||
lightAttnFn = fmt::format(FMT_STRING(R"""(
|
||||
var cosine = max(0.0, dot(ldir, light.dir));
|
||||
var cos_attn = dot(light.ang_att, vec3<f32>(1.0, cosine, cosine * cosine));
|
||||
var dist_attn = dot(light.lin_att, vec3<f32>(1.0, dist, dist2));
|
||||
attn = max(0.0, cos_attn / dist_attn);)"""));
|
||||
} else if (cc.attnFn == GX::AF_SPEC) {
|
||||
diffFn = GX::DF_NONE;
|
||||
Log.report(logvisor::Fatal, FMT_STRING("AF_SPEC unimplemented"));
|
||||
}
|
||||
if (diffFn == GX::DF_NONE) {
|
||||
lightDiffFn = "1.0";
|
||||
} else if (diffFn == GX::DF_SIGN) {
|
||||
lightDiffFn = "dot(ldir, mv_nrm)";
|
||||
} else if (diffFn == GX::DF_CLAMP) {
|
||||
lightDiffFn = "max(0.0, dot(ldir, mv_nrm))";
|
||||
}
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
||||
{{
|
||||
var lighting = ubuf.lighting_ambient{0} + ubuf.cc{0}_amb;
|
||||
var lighting = {5};
|
||||
for (var i = 0; i < {1}; i = i + 1) {{
|
||||
var light = ubuf.lights{0}[i];
|
||||
var delta = mv_pos.xyz - light.pos;
|
||||
var dist = length(delta);
|
||||
var delta_norm = delta / dist;
|
||||
var ang_dot = max(dot(delta_norm, light.dir), 0.0);
|
||||
var att = 1.0 / (light.lin_att.z * dist * dist +
|
||||
light.lin_att.y * dist +
|
||||
light.lin_att.x);
|
||||
var ang_att = light.ang_att.z * ang_dot * ang_dot +
|
||||
light.ang_att.y * ang_dot +
|
||||
light.ang_att.x;
|
||||
var this_color = light.color.xyz * ang_att * att * max(dot(-delta_norm, mv_nrm), 0.0);
|
||||
lighting = lighting + vec4<f32>(this_color, 0.0);
|
||||
var ldir = light.pos - mv_pos;
|
||||
var dist2 = dot(ldir, ldir);
|
||||
var dist = sqrt(dist2);
|
||||
ldir = ldir / dist;
|
||||
var attn: f32;{2}
|
||||
var diff = {3};
|
||||
lighting = lighting + (attn * diff * light.color);
|
||||
}}
|
||||
out.cc{0} = clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
||||
out.cc{0} = {4} * clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
||||
}})"""),
|
||||
i, GX::MaxLights);
|
||||
i, GX::MaxLights, lightAttnFn, lightDiffFn, matSrc, ambSrc);
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else if (config.colorChannels[i].matSrc == GX::SRC_VTX) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), vtxOutIdx++, i);
|
||||
} else if (cc.matSrc == GX::SRC_VTX) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>,"), vtxOutIdx++, i);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = {};"), i, vtx_attr(config, GX::Attr(GX::VA_CLR0 + i)));
|
||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||
} else {
|
||||
|
@ -888,7 +914,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
}
|
||||
for (int i = 0; i < info.sampledKColors.size(); ++i) {
|
||||
if (info.sampledKColors.test(i)) {
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>,"), i);
|
||||
}
|
||||
}
|
||||
size_t texBindIdx = 0;
|
||||
|
@ -897,7 +923,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
continue;
|
||||
}
|
||||
const auto& tcg = config.tcgs[i];
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), vtxOutIdx++, i);
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>,"), vtxOutIdx++, i);
|
||||
if (tcg.src >= GX::TG_TEX0 && tcg.src <= GX::TG_TEX7) {
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n var tc{} = vec4<f32>({}, 0.0, 1.0);"), i,
|
||||
vtx_attr(config, GX::Attr(GX::VA_TEX0 + (tcg.src - GX::TG_TEX0))));
|
||||
|
@ -941,10 +967,10 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
if (info.usesTexMtx.test(i)) {
|
||||
switch (info.texMtxTypes[i]) {
|
||||
case GX::TG_MTX2x4:
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x2<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x2<f32>,"), i);
|
||||
break;
|
||||
case GX::TG_MTX3x4:
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x3<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n texmtx{}: mat4x3<f32>,"), i);
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, FMT_STRING("unhandled tex mtx type {}"), info.texMtxTypes[i]);
|
||||
|
@ -954,20 +980,20 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
}
|
||||
for (int i = 0; i < info.usesPTTexMtx.size(); ++i) {
|
||||
if (info.usesPTTexMtx.test(i)) {
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n postmtx{}: mat4x3<f32>;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n postmtx{}: mat4x3<f32>,"), i);
|
||||
}
|
||||
}
|
||||
if (info.usesFog) {
|
||||
uniformPre +=
|
||||
"\n"
|
||||
"struct Fog {\n"
|
||||
" color: vec4<f32>;\n"
|
||||
" a: f32;\n"
|
||||
" b: f32;\n"
|
||||
" c: f32;\n"
|
||||
" pad: f32;\n"
|
||||
" color: vec4<f32>,\n"
|
||||
" a: f32,\n"
|
||||
" b: f32,\n"
|
||||
" c: f32,\n"
|
||||
" pad: f32,\n"
|
||||
"}";
|
||||
uniBufAttrs += "\n fog: Fog;";
|
||||
uniBufAttrs += "\n fog: Fog,";
|
||||
|
||||
fragmentFn += "\n var fogF = clamp((ubuf.fog.a / (ubuf.fog.b - in.pos.z)) - ubuf.fog.c, 0.0, 1.0);";
|
||||
switch (config.fogType) {
|
||||
|
@ -1003,7 +1029,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32;"), i);
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32,"), i);
|
||||
|
||||
sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({})\n"
|
||||
"var tex{}_samp: sampler;"),
|
||||
|
@ -1046,15 +1072,15 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
|||
const auto shaderSource =
|
||||
fmt::format(FMT_STRING(R"""({uniformPre}
|
||||
struct Uniform {{
|
||||
pos_mtx: mat4x3<f32>;
|
||||
nrm_mtx: mat4x3<f32>;
|
||||
proj: mat4x4<f32>;{uniBufAttrs}
|
||||
pos_mtx: mat4x3<f32>,
|
||||
nrm_mtx: mat4x3<f32>,
|
||||
proj: mat4x4<f32>,{uniBufAttrs}
|
||||
}};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
|
||||
|
||||
struct VertexOutput {{
|
||||
@builtin(position) pos: vec4<f32>;{vtxOutAttrs}
|
||||
@builtin(position) pos: vec4<f32>,{vtxOutAttrs}
|
||||
}};
|
||||
|
||||
@stage(vertex)
|
||||
|
|
Loading…
Reference in New Issue