mirror of https://github.com/AxioDL/metaforce.git
aurora: Support per-pixel lighting
This commit is contained in:
parent
05ad95bdd0
commit
fe65258d91
|
@ -754,8 +754,7 @@ const wgpu::Sampler& sampler_ref(const wgpu::SamplerDescriptor& descriptor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t align_uniform(uint32_t value) {
|
uint32_t align_uniform(uint32_t value) {
|
||||||
const auto uniform_alignment = g_cachedLimits.limits.minUniformBufferOffsetAlignment;
|
return ALIGN(value, g_cachedLimits.limits.minUniformBufferOffsetAlignment);
|
||||||
return ALIGN(value, uniform_alignment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_debug_group(zstring_view label) noexcept {
|
void push_debug_group(zstring_view label) noexcept {
|
||||||
|
|
|
@ -891,12 +891,22 @@ void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) n
|
||||||
}
|
}
|
||||||
config.shaderConfig.tevStageCount = g_gxState.numTevStages;
|
config.shaderConfig.tevStageCount = g_gxState.numTevStages;
|
||||||
for (u8 i = 0; i < g_gxState.numChans; ++i) {
|
for (u8 i = 0; i < g_gxState.numChans; ++i) {
|
||||||
config.shaderConfig.colorChannels[i] = g_gxState.colorChannelConfig[i];
|
const auto& cc = g_gxState.colorChannelConfig[i];
|
||||||
|
if (g_gxState.colorChannelState[i].lightState.any() && cc.lightingEnabled) {
|
||||||
|
config.shaderConfig.colorChannels[i] = cc;
|
||||||
|
} else {
|
||||||
|
// Only matSrc matters when lighting disabled
|
||||||
|
config.shaderConfig.colorChannels[i] = {
|
||||||
|
.matSrc = cc.matSrc,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (u8 i = 0; i < g_gxState.numTexGens; ++i) {
|
for (u8 i = 0; i < g_gxState.numTexGens; ++i) {
|
||||||
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
config.shaderConfig.tcgs[i] = g_gxState.tcgs[i];
|
||||||
}
|
}
|
||||||
|
if (g_gxState.alphaCompare) {
|
||||||
config.shaderConfig.alphaCompare = g_gxState.alphaCompare;
|
config.shaderConfig.alphaCompare = g_gxState.alphaCompare;
|
||||||
|
}
|
||||||
config.shaderConfig.indexedAttributeCount =
|
config.shaderConfig.indexedAttributeCount =
|
||||||
std::count_if(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
std::count_if(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
||||||
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; });
|
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; });
|
||||||
|
@ -904,8 +914,12 @@ void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) n
|
||||||
const auto& bind = g_gxState.textures[i];
|
const auto& bind = g_gxState.textures[i];
|
||||||
TextureConfig texConfig{};
|
TextureConfig texConfig{};
|
||||||
if (bind.texObj.ref) {
|
if (bind.texObj.ref) {
|
||||||
|
if (requires_copy_conversion(bind.texObj)) {
|
||||||
texConfig.copyFmt = bind.texObj.ref->gxFormat;
|
texConfig.copyFmt = bind.texObj.ref->gxFormat;
|
||||||
|
}
|
||||||
|
if (requires_load_conversion(bind.texObj)) {
|
||||||
texConfig.loadFmt = bind.texObj.fmt;
|
texConfig.loadFmt = bind.texObj.fmt;
|
||||||
|
}
|
||||||
texConfig.renderTex = bind.texObj.ref->isRenderTexture;
|
texConfig.renderTex = bind.texObj.ref->isRenderTexture;
|
||||||
}
|
}
|
||||||
config.shaderConfig.textureConfig[i] = texConfig;
|
config.shaderConfig.textureConfig[i] = texConfig;
|
||||||
|
@ -934,8 +948,8 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
||||||
buf.append(&g_gxState.mvInv, 64);
|
buf.append(&g_gxState.mvInv, 64);
|
||||||
buf.append(&g_gxState.proj, 64);
|
buf.append(&g_gxState.proj, 64);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < info.usesTevReg.size(); ++i) {
|
for (int i = 0; i < info.loadsTevReg.size(); ++i) {
|
||||||
if (!info.usesTevReg.test(i)) {
|
if (!info.loadsTevReg.test(i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
buf.append(&g_gxState.colorRegs[i], 16);
|
buf.append(&g_gxState.colorRegs[i], 16);
|
||||||
|
@ -950,6 +964,9 @@ Range build_uniform(const ShaderInfo& info) noexcept {
|
||||||
if (g_gxState.colorChannelConfig[i].lightingEnabled) {
|
if (g_gxState.colorChannelConfig[i].lightingEnabled) {
|
||||||
int addedLights = 0;
|
int addedLights = 0;
|
||||||
const auto& lightState = g_gxState.colorChannelState[i].lightState;
|
const auto& lightState = g_gxState.colorChannelState[i].lightState;
|
||||||
|
u32 state = lightState.to_ulong();
|
||||||
|
buf.append(&lightState, sizeof(u32));
|
||||||
|
buf.append_zeroes(12); // alignment
|
||||||
for (int li = 0; li < lightState.size(); ++li) {
|
for (int li = 0; li < lightState.size(); ++li) {
|
||||||
if (!lightState.test(li)) {
|
if (!lightState.test(li)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -80,9 +80,7 @@ struct TextureBind {
|
||||||
|
|
||||||
TextureBind() noexcept = default;
|
TextureBind() noexcept = default;
|
||||||
TextureBind(GXTexObj obj) noexcept : texObj(std::move(obj)) {}
|
TextureBind(GXTexObj obj) noexcept : texObj(std::move(obj)) {}
|
||||||
void reset() noexcept {
|
void reset() noexcept { texObj.ref.reset(); };
|
||||||
texObj.ref.reset();
|
|
||||||
};
|
|
||||||
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
||||||
operator bool() const noexcept { return texObj.ref.operator bool(); }
|
operator bool() const noexcept { return texObj.ref.operator bool(); }
|
||||||
};
|
};
|
||||||
|
@ -144,7 +142,7 @@ struct AlphaCompare {
|
||||||
GX::Compare comp1 = GX::ALWAYS;
|
GX::Compare comp1 = GX::ALWAYS;
|
||||||
u32 ref1;
|
u32 ref1;
|
||||||
bool operator==(const AlphaCompare& other) const = default;
|
bool operator==(const AlphaCompare& other) const = default;
|
||||||
operator bool() const { return *this != AlphaCompare{}; }
|
operator bool() const { return comp0 != GX::ALWAYS || comp1 != GX::ALWAYS; }
|
||||||
};
|
};
|
||||||
static_assert(std::has_unique_object_representations_v<AlphaCompare>);
|
static_assert(std::has_unique_object_representations_v<AlphaCompare>);
|
||||||
struct IndTexMtxInfo {
|
struct IndTexMtxInfo {
|
||||||
|
@ -202,6 +200,41 @@ static inline Mat4x4<float> get_combined_matrix() noexcept { return g_gxState.pr
|
||||||
void shutdown() noexcept;
|
void shutdown() noexcept;
|
||||||
const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
const TextureBind& get_texture(GX::TexMapID id) noexcept;
|
||||||
|
|
||||||
|
static inline bool requires_copy_conversion(const GXTexObj& obj) {
|
||||||
|
if (!obj.ref) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj.ref->isRenderTexture) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (obj.ref->gxFormat) {
|
||||||
|
// case GX::TF_RGB565:
|
||||||
|
// case GX::TF_I4:
|
||||||
|
// case GX::TF_I8:
|
||||||
|
case GX::TF_C4:
|
||||||
|
case GX::TF_C8:
|
||||||
|
case GX::TF_C14X2:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline bool requires_load_conversion(const GXTexObj& obj) {
|
||||||
|
if (!obj.ref) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (obj.fmt) {
|
||||||
|
case GX::TF_I4:
|
||||||
|
case GX::TF_I8:
|
||||||
|
case GX::TF_C4:
|
||||||
|
case GX::TF_C8:
|
||||||
|
case GX::TF_C14X2:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct TextureConfig {
|
struct TextureConfig {
|
||||||
GX::TextureFormat copyFmt = InvalidTextureFormat; // Underlying texture format
|
GX::TextureFormat copyFmt = InvalidTextureFormat; // Underlying texture format
|
||||||
GX::TextureFormat loadFmt = InvalidTextureFormat; // Texture format being bound
|
GX::TextureFormat loadFmt = InvalidTextureFormat; // Texture format being bound
|
||||||
|
@ -257,7 +290,7 @@ struct ShaderInfo {
|
||||||
std::bitset<MaxTextures> sampledTextures;
|
std::bitset<MaxTextures> sampledTextures;
|
||||||
std::bitset<MaxKColors> sampledKColors;
|
std::bitset<MaxKColors> sampledKColors;
|
||||||
std::bitset<MaxColorChannels> sampledColorChannels;
|
std::bitset<MaxColorChannels> sampledColorChannels;
|
||||||
std::bitset<MaxTevRegs> usesTevReg;
|
std::bitset<MaxTevRegs> loadsTevReg;
|
||||||
std::bitset<MaxTevRegs> writesTevReg;
|
std::bitset<MaxTevRegs> writesTevReg;
|
||||||
std::bitset<MaxTexMtx> usesTexMtx;
|
std::bitset<MaxTexMtx> usesTexMtx;
|
||||||
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
std::bitset<MaxPTTexMtx> usesPTTexMtx;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
constexpr bool EnableNormalVisualization = false;
|
constexpr bool EnableNormalVisualization = false;
|
||||||
constexpr bool EnableDebugPrints = true;
|
constexpr bool EnableDebugPrints = true;
|
||||||
|
constexpr bool UsePerPixelLighting = true;
|
||||||
|
|
||||||
namespace aurora::gfx::gx {
|
namespace aurora::gfx::gx {
|
||||||
using namespace fmt::literals;
|
using namespace fmt::literals;
|
||||||
|
@ -36,25 +37,25 @@ static void color_arg_reg_info(GX::TevColorArg arg, const TevStage& stage, Shade
|
||||||
case GX::CC_CPREV:
|
case GX::CC_CPREV:
|
||||||
case GX::CC_APREV:
|
case GX::CC_APREV:
|
||||||
if (!info.writesTevReg.test(GX::TEVPREV)) {
|
if (!info.writesTevReg.test(GX::TEVPREV)) {
|
||||||
info.usesTevReg.set(GX::TEVPREV);
|
info.loadsTevReg.set(GX::TEVPREV);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CC_C0:
|
case GX::CC_C0:
|
||||||
case GX::CC_A0:
|
case GX::CC_A0:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG0)) {
|
if (!info.writesTevReg.test(GX::TEVREG0)) {
|
||||||
info.usesTevReg.set(GX::TEVREG0);
|
info.loadsTevReg.set(GX::TEVREG0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CC_C1:
|
case GX::CC_C1:
|
||||||
case GX::CC_A1:
|
case GX::CC_A1:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG1)) {
|
if (!info.writesTevReg.test(GX::TEVREG1)) {
|
||||||
info.usesTevReg.set(GX::TEVREG1);
|
info.loadsTevReg.set(GX::TEVREG1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CC_C2:
|
case GX::CC_C2:
|
||||||
case GX::CC_A2:
|
case GX::CC_A2:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG2)) {
|
if (!info.writesTevReg.test(GX::TEVREG2)) {
|
||||||
info.usesTevReg.set(GX::TEVREG2);
|
info.loadsTevReg.set(GX::TEVREG2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CC_TEXC:
|
case GX::CC_TEXC:
|
||||||
|
@ -299,22 +300,22 @@ static void alpha_arg_reg_info(GX::TevAlphaArg arg, const TevStage& stage, Shade
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case GX::CA_APREV:
|
case GX::CA_APREV:
|
||||||
if (!info.writesTevReg.test(GX::TEVPREV)) {
|
if (!info.writesTevReg.test(GX::TEVPREV)) {
|
||||||
info.usesTevReg.set(GX::TEVPREV);
|
info.loadsTevReg.set(GX::TEVPREV);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CA_A0:
|
case GX::CA_A0:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG0)) {
|
if (!info.writesTevReg.test(GX::TEVREG0)) {
|
||||||
info.usesTevReg.set(GX::TEVREG0);
|
info.loadsTevReg.set(GX::TEVREG0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CA_A1:
|
case GX::CA_A1:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG1)) {
|
if (!info.writesTevReg.test(GX::TEVREG1)) {
|
||||||
info.usesTevReg.set(GX::TEVREG1);
|
info.loadsTevReg.set(GX::TEVREG1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CA_A2:
|
case GX::CA_A2:
|
||||||
if (!info.writesTevReg.test(GX::TEVREG2)) {
|
if (!info.writesTevReg.test(GX::TEVREG2)) {
|
||||||
info.usesTevReg.set(GX::TEVREG2);
|
info.loadsTevReg.set(GX::TEVREG2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GX::CA_TEXA:
|
case GX::CA_TEXA:
|
||||||
|
@ -636,16 +637,16 @@ ShaderInfo build_shader_info(const ShaderConfig& config) noexcept {
|
||||||
if (!info.writesTevReg.test(stage.alphaOp.outReg)) {
|
if (!info.writesTevReg.test(stage.alphaOp.outReg)) {
|
||||||
// If we're writing alpha to a register that's not been
|
// If we're writing alpha to a register that's not been
|
||||||
// written to in the shader, load from uniform buffer
|
// written to in the shader, load from uniform buffer
|
||||||
info.usesTevReg.set(stage.alphaOp.outReg);
|
info.loadsTevReg.set(stage.alphaOp.outReg);
|
||||||
info.writesTevReg.set(stage.alphaOp.outReg);
|
info.writesTevReg.set(stage.alphaOp.outReg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.uniformSize += info.usesTevReg.count() * 16;
|
info.uniformSize += info.loadsTevReg.count() * 16;
|
||||||
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
|
||||||
if (info.sampledColorChannels.test(i)) {
|
if (info.sampledColorChannels.test(i)) {
|
||||||
info.uniformSize += 32;
|
info.uniformSize += 32;
|
||||||
if (config.colorChannels[i].lightingEnabled) {
|
if (config.colorChannels[i].lightingEnabled) {
|
||||||
info.uniformSize += (80 * GX::MaxLights);
|
info.uniformSize += 16 + (80 * GX::MaxLights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -883,7 +884,8 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
if (stage.colorOp.clamp) {
|
if (stage.colorOp.clamp) {
|
||||||
op = fmt::format(FMT_STRING("clamp({}, vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
op = fmt::format(FMT_STRING("clamp({}, vec3<f32>(0.0), vec3<f32>(1.0))"), op);
|
||||||
}
|
}
|
||||||
fragmentFn += fmt::format(FMT_STRING("\n // TEV stage {2}\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op, idx);
|
fragmentFn +=
|
||||||
|
fmt::format(FMT_STRING("\n // TEV stage {2}\n {0} = vec4<f32>({1}, {0}.a);"), outReg, op, idx);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::string outReg;
|
std::string outReg;
|
||||||
|
@ -914,14 +916,14 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
fragmentFn += fmt::format(FMT_STRING("\n {0} = {1};"), outReg, op);
|
fragmentFn += fmt::format(FMT_STRING("\n {0} = {1};"), outReg, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.usesTevReg.test(0)) {
|
if (info.loadsTevReg.test(0)) {
|
||||||
uniBufAttrs += "\n tevprev: vec4<f32>,";
|
uniBufAttrs += "\n tevprev: vec4<f32>,";
|
||||||
fragmentFnPre += "\n var prev = ubuf.tevprev;";
|
fragmentFnPre += "\n var prev = ubuf.tevprev;";
|
||||||
} else {
|
} else {
|
||||||
fragmentFnPre += "\n var prev: vec4<f32>;";
|
fragmentFnPre += "\n var prev: vec4<f32>;";
|
||||||
}
|
}
|
||||||
for (int i = 1 /* Skip TEVPREV */; i < info.usesTevReg.size(); ++i) {
|
for (int i = 1 /* Skip TEVPREV */; i < info.loadsTevReg.size(); ++i) {
|
||||||
if (info.usesTevReg.test(i)) {
|
if (info.loadsTevReg.test(i)) {
|
||||||
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>,"), i - 1);
|
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>,"), i - 1);
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i - 1);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i - 1);
|
||||||
} else if (info.writesTevReg.test(i)) {
|
} else if (info.writesTevReg.test(i)) {
|
||||||
|
@ -949,11 +951,18 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
" cos_att: vec3<f32>,\n"
|
" cos_att: vec3<f32>,\n"
|
||||||
" dist_att: vec3<f32>,\n"
|
" dist_att: vec3<f32>,\n"
|
||||||
"};";
|
"};";
|
||||||
|
if (UsePerPixelLighting) {
|
||||||
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) mv_pos: vec3<f32>,"), vtxOutIdx++);
|
||||||
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) mv_nrm: vec3<f32>,"), vtxOutIdx++);
|
||||||
|
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
||||||
|
out.mv_pos = mv_pos;
|
||||||
|
out.mv_nrm = mv_nrm;)"""));
|
||||||
|
}
|
||||||
addedLightStruct = true;
|
addedLightStruct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uniBufAttrs += fmt::format(FMT_STRING("\n lightState{}: u32,"), i);
|
||||||
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>,"), i, GX::MaxLights);
|
uniBufAttrs += fmt::format(FMT_STRING("\n lights{}: array<Light, {}>,"), i, GX::MaxLights);
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>,"), vtxOutIdx++, i);
|
|
||||||
|
|
||||||
std::string ambSrc, matSrc, lightAttnFn, lightDiffFn;
|
std::string ambSrc, matSrc, lightAttnFn, lightDiffFn;
|
||||||
if (cc.ambSrc == GX::SRC_VTX) {
|
if (cc.ambSrc == GX::SRC_VTX) {
|
||||||
|
@ -982,16 +991,33 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
if (diffFn == GX::DF_NONE) {
|
if (diffFn == GX::DF_NONE) {
|
||||||
lightDiffFn = "1.0";
|
lightDiffFn = "1.0";
|
||||||
} else if (diffFn == GX::DF_SIGN) {
|
} else if (diffFn == GX::DF_SIGN) {
|
||||||
|
if (UsePerPixelLighting) {
|
||||||
|
lightDiffFn = "dot(ldir, in.mv_nrm)";
|
||||||
|
} else {
|
||||||
lightDiffFn = "dot(ldir, mv_nrm)";
|
lightDiffFn = "dot(ldir, mv_nrm)";
|
||||||
|
}
|
||||||
} else if (diffFn == GX::DF_CLAMP) {
|
} else if (diffFn == GX::DF_CLAMP) {
|
||||||
|
if (UsePerPixelLighting) {
|
||||||
|
lightDiffFn = "max(0.0, dot(ldir, in.mv_nrm))";
|
||||||
|
} else {
|
||||||
lightDiffFn = "max(0.0, dot(ldir, mv_nrm))";
|
lightDiffFn = "max(0.0, dot(ldir, mv_nrm))";
|
||||||
}
|
}
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
|
}
|
||||||
|
std::string outVar, posVar;
|
||||||
|
if (UsePerPixelLighting) {
|
||||||
|
outVar = fmt::format(FMT_STRING("rast{}"), i);
|
||||||
|
posVar = "in.mv_pos";
|
||||||
|
} else {
|
||||||
|
outVar = fmt::format(FMT_STRING("out.cc{}"), i);
|
||||||
|
posVar = "mv_pos";
|
||||||
|
}
|
||||||
|
auto lightFunc = fmt::format(FMT_STRING(R"""(
|
||||||
{{
|
{{
|
||||||
var lighting = {5};
|
var lighting = {5};
|
||||||
for (var i = 0; i < {1}; i = i + 1) {{
|
for (var i = 0u; i < {1}u; i++) {{
|
||||||
|
if ((ubuf.lightState{0} & (1u << i)) == 0u) {{ continue; }}
|
||||||
var light = ubuf.lights{0}[i];
|
var light = ubuf.lights{0}[i];
|
||||||
var ldir = light.pos - mv_pos;
|
var ldir = light.pos - {7};
|
||||||
var dist2 = dot(ldir, ldir);
|
var dist2 = dot(ldir, ldir);
|
||||||
var dist = sqrt(dist2);
|
var dist = sqrt(dist2);
|
||||||
ldir = ldir / dist;
|
ldir = ldir / dist;
|
||||||
|
@ -999,10 +1025,17 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
var diff = {3};
|
var diff = {3};
|
||||||
lighting = lighting + (attn * diff * light.color);
|
lighting = lighting + (attn * diff * light.color);
|
||||||
}}
|
}}
|
||||||
out.cc{0} = {4} * clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
{6} = {4} * clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
|
||||||
}})"""),
|
}})"""),
|
||||||
i, GX::MaxLights, lightAttnFn, lightDiffFn, matSrc, ambSrc);
|
i, GX::MaxLights, lightAttnFn, lightDiffFn, matSrc, ambSrc, outVar, posVar);
|
||||||
|
if (UsePerPixelLighting) {
|
||||||
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{}: vec4<f32>;"), i);
|
||||||
|
fragmentFnPre += lightFunc;
|
||||||
|
} else {
|
||||||
|
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>,"), vtxOutIdx++, i);
|
||||||
|
vtxXfrAttrs += lightFunc;
|
||||||
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
|
||||||
|
}
|
||||||
} else if (cc.matSrc == GX::SRC_VTX) {
|
} else if (cc.matSrc == GX::SRC_VTX) {
|
||||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>,"), vtxOutIdx++, i);
|
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)));
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = {};"), i, vtx_attr(config, GX::Attr(GX::VA_CLR0 + i)));
|
||||||
|
|
Loading…
Reference in New Issue