Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions include/aurora/gfx.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ const AuroraStats* aurora_get_stats();

void aurora_enable_vsync(bool enabled);

void aurora_set_enhanced_lighting(bool enabled);
bool aurora_get_enhanced_lighting();

void aurora_set_specular_lighting(bool enabled);
bool aurora_get_specular_lighting();
void aurora_set_rim_lighting(bool enabled);
bool aurora_get_rim_lighting();
void aurora_set_specular_intensity(float intensity);
float aurora_get_specular_intensity();
void aurora_set_rim_intensity(float intensity);
float aurora_get_rim_intensity();
void aurora_set_ambient_multiplier(float multiplier);
float aurora_get_ambient_multiplier();
void aurora_set_diffuse_multiplier(float multiplier);
float aurora_get_diffuse_multiplier();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public API looks kind of awkward, I think. Would it make sense to pass these all in at once? EnhancedLightingState or something?


#ifdef __cplusplus
}
#endif
Expand Down
16 changes: 16 additions & 0 deletions lib/gfx/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1058,3 +1058,19 @@ void pop_debug_group() {
}

const AuroraStats* aurora_get_stats() { return &aurora::gfx::g_stats; }

void aurora_set_enhanced_lighting(const bool enabled) { aurora::gx::g_enhancedLighting = enabled; }
bool aurora_get_enhanced_lighting() { return aurora::gx::g_enhancedLighting; }

void aurora_set_specular_lighting(const bool enabled) { aurora::gx::g_enableSpecular = enabled; }
bool aurora_get_specular_lighting() { return aurora::gx::g_enableSpecular; }
void aurora_set_rim_lighting(const bool enabled) { aurora::gx::g_enableRim = enabled; }
bool aurora_get_rim_lighting() { return aurora::gx::g_enableRim; }
void aurora_set_specular_intensity(const float intensity) { aurora::gx::g_specularIntensity = intensity; }
float aurora_get_specular_intensity() { return aurora::gx::g_specularIntensity; }
void aurora_set_rim_intensity(const float intensity) { aurora::gx::g_rimIntensity = intensity; }
float aurora_get_rim_intensity() { return aurora::gx::g_rimIntensity; }
void aurora_set_ambient_multiplier(const float multiplier) { aurora::gx::g_ambientMultiplier = multiplier; }
float aurora_get_ambient_multiplier() { return aurora::gx::g_ambientMultiplier; }
void aurora_set_diffuse_multiplier(const float multiplier) { aurora::gx::g_diffuseMultiplier = multiplier; }
float aurora_get_diffuse_multiplier() { return aurora::gx::g_diffuseMultiplier; }
11 changes: 11 additions & 0 deletions lib/gx/gx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,14 @@ u8 comp_cnt_count(GXAttr attr, GXCompCnt cnt) noexcept {
Log.fatal("comp_cnt_count: Unsupported attr/cnt {} {}", attr, cnt);
}

bool g_enhancedLighting = true;
bool g_enableSpecular = true;
bool g_enableRim = true;
float g_specularIntensity = 0.2f;
float g_rimIntensity = 0.08f;
float g_ambientMultiplier = 1.0f;
float g_diffuseMultiplier = 1.0f;

void populate_pipeline_config(PipelineConfig& config, GXPrimitive primitive, GXVtxFmt fmt) noexcept {
ZoneScoped;

Expand Down Expand Up @@ -787,6 +795,9 @@ void populate_pipeline_config(PipelineConfig& config, GXPrimitive primitive, GXV
config.shaderConfig.indStages[i] = g_gxState.indStages[i];
}
config.shaderConfig.numIndStages = g_gxState.numIndStages;
config.shaderConfig.enhancedLighting = g_enhancedLighting ? 1 : 0;
config.shaderConfig.enableSpecular = g_enableSpecular ? 1 : 0;
config.shaderConfig.enableRim = g_enableRim ? 1 : 0;
for (u8 i = 0; i < MaxColorChannels; ++i) {
const auto& cc = g_gxState.colorChannelConfig[i];
if (cc.lightingEnabled) {
Expand Down
15 changes: 13 additions & 2 deletions lib/gx/gx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ constexpr float GX_LARGE_NUMBER = -1048576.0f;
namespace aurora::gx {
constexpr bool EnableNormalVisualization = false;
constexpr bool EnableDebugPrints = false;
constexpr bool UsePerPixelLighting = false;
constexpr bool UsePerPixelLighting = true;
constexpr bool UseReversedZ = true;

constexpr u32 MaxTextures = GX_MAX_TEXMAP;
Expand Down Expand Up @@ -383,6 +383,13 @@ struct GXState {
void clearVtxSizeCache() { lastVtxFmt = GX_MAX_VTXFMT; }
};
extern GXState g_gxState;
extern bool g_enhancedLighting;
extern bool g_enableSpecular;
extern bool g_enableRim;
extern float g_specularIntensity;
extern float g_rimIntensity;
extern float g_ambientMultiplier;
extern float g_diffuseMultiplier;
Comment on lines +386 to +392
Copy link
Copy Markdown
Owner

@encounter encounter May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be best to wrap these in a struct of some kind. maybe ExtState (or reuse EnhancedLightingState if it makes sense)

struct ShaderInfo;

void initialize() noexcept;
Expand Down Expand Up @@ -439,7 +446,10 @@ struct ShaderConfig {
u8 fogType = GX_FOG_NONE;
u8 vtxStride = 0;
u8 lineMode : 2 = 0; // 1 = GX_LINES, 2 = GX_LINESTRIP, 3 = GX_POINTS
u8 pad1 : 6 = 0;
u8 enhancedLighting : 1 = 1;
u8 enableSpecular : 1 = 1;
u8 enableRim : 1 = 1;
u8 pad1 : 3 = 0;
u8 pad2 = 0;
std::array<AttrConfig, MaxVtxAttr> attrs;
std::array<TevSwap, MaxTevSwap> tevSwapTable;
Expand Down Expand Up @@ -476,6 +486,7 @@ struct ShaderInfo {
u32 uniformSize = 0;
bool usesFog : 1 = false;
bool lightingEnabled : 1 = false;
bool enhancedLighting : 1 = false;
u8 lineMode : 2 = 0;
};
struct BindGroupRanges {
Expand Down
61 changes: 48 additions & 13 deletions lib/gx/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
std::string_view swizzle = alpha ? ".a"sv : ""sv;
std::string outVar;
std::string_view posVar;
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
outVar = fmt::format("rast{}", i);
posVar = "in.mv_pos"sv;
} else {
Expand All @@ -601,7 +601,7 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
}
std::string ambSrc, matSrc;
if (cc.ambSrc == GX_SRC_VTX) {
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
ambSrc = fmt::format("in.clr{}", i);
} else {
ambSrc = vtx_attr(config, static_cast<GXAttr>(GX_VA_CLR0 + i));
Expand All @@ -610,7 +610,7 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
ambSrc = fmt::format("ubuf.cc{0}{1}_amb", i, alpha ? "a"sv : ""sv);
}
if (cc.matSrc == GX_SRC_VTX) {
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
matSrc = fmt::format("in.clr{}", i);
} else {
matSrc = vtx_attr(config, static_cast<GXAttr>(GX_VA_CLR0 + i));
Expand All @@ -632,7 +632,7 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
var dist_attn = dot(light.dist_att, vec3f(1.0, dist, dist2));
attn = max(0.0, cos_attn / dist_attn);)""");
} else if (cc.attnFn == GX_AF_SPEC) {
std::string_view normal = UsePerPixelLighting ? "in.mv_nrm"sv : "mv_nrm"sv;
std::string_view normal = config.enhancedLighting ? "in.mv_nrm"sv : "mv_nrm"sv;
std::string dist_attn = diffFn != GX_DF_NONE
? "max(0.0, dot(normalize(light.dist_att), vec3f(1.0, attn, attn * attn)));"
: "max(0.0, dot(light.dist_att, vec3f(1.0, attn, attn * attn)));";
Expand All @@ -647,21 +647,49 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
if (diffFn == GX_DF_NONE) {
lightDiffFn = "1.0"sv;
} else if (diffFn == GX_DF_SIGN) {
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
lightDiffFn = "dot(ldir, in.mv_nrm)"sv;
} else {
lightDiffFn = "dot(ldir, mv_nrm)"sv;
}
} else if (diffFn == GX_DF_CLAMP) {
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
lightDiffFn = "max(0.0, dot(ldir, in.mv_nrm))"sv;
} else {
lightDiffFn = "max(0.0, dot(ldir, mv_nrm))"sv;
}
}
// Blinn-Phong specular + rim lighting for per-pixel lighting
// Skips GX_AF_SPEC (which already computes specular in a worse way)
std::string ambientScale;
std::string diffuseScale;
std::string viewDirCode;
std::string specularCode;
std::string postLoopCode;
if (config.enhancedLighting) {
ambientScale = " * ubuf.ambient_multiplier";
diffuseScale = " * ubuf.diffuse_multiplier";
if (!alpha && diffFn != GX_DF_NONE && cc.attnFn != GX_AF_SPEC &&
(config.enableSpecular || config.enableRim)) {
viewDirCode = R"""(
let view_dir = normalize(-in.mv_pos);)""";
if (config.enableSpecular) {
specularCode = R"""(
if (diff > 0.0) {
let h = normalize(ldir + view_dir);
spec_contrib = pow(max(0.0, dot(in.mv_nrm, h)), 32.0) * ubuf.specular_intensity;
})""";
}
if (config.enableRim) {
postLoopCode = R"""(
let rim = pow(1.0 - max(0.0, dot(view_dir, in.mv_nrm)), 3.0) * ubuf.rim_intensity;
lighting = lighting + vec4f(rim, rim, rim, 0.0);)""";
}
}
}
return fmt::format(R"""(
{{
var lighting = {5};
var lighting = {5}{13};{11}
for (var i = 0u; i < {1}u; i++) {{
if ((ubuf.lightState{0}{9} & (1u << i)) == 0u) {{ continue; }}
var light = ubuf.lights[i];
Expand All @@ -671,12 +699,13 @@ auto lighting_func(const ShaderConfig& config, const ColorChannelConfig& cc, u8
ldir = ldir / dist;
var attn: f32;{2}
var diff = {3};
lighting = lighting + (attn * diff * light.color);
}}
var spec_contrib: f32 = 0.0;{10}
lighting = lighting + (attn * (diff{14} + spec_contrib) * light.color);
}}{12}
{7}{8} = ({4} * clamp(lighting, vec4f(0.0), vec4f(1.0))){8};
}})""",
i, GX::MaxLights, lightAttnFn, lightDiffFn, matSrc, ambSrc, posVar, outVar, swizzle,
alpha ? "a"sv : ""sv);
alpha ? "a"sv : ""sv, specularCode, viewDirCode, postLoopCode, ambientScale, diffuseScale);
}

wgpu::ShaderModule build_shader(const ShaderConfig& config) noexcept {
Expand Down Expand Up @@ -927,6 +956,12 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config) noexcept {
lightState0a: u32,
lightState1a: u32,)"""),
GX::MaxLights);
if (config.enhancedLighting) {
uniBufAttrs += "\n specular_intensity: f32,";
uniBufAttrs += "\n rim_intensity: f32,";
uniBufAttrs += "\n ambient_multiplier: f32,";
uniBufAttrs += "\n diffuse_multiplier: f32,";
}
uniformPre +=
"\n"
"struct Light {\n"
Expand All @@ -936,7 +971,7 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config) noexcept {
" cos_att: vec3f,\n"
" dist_att: vec3f,\n"
"};";
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
vtxOutAttrs += fmt::format("\n @location({}) mv_pos: vec3f,", vtxOutIdx++);
vtxOutAttrs += fmt::format("\n @location({}) mv_nrm: vec3f,", vtxOutIdx++);
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
Expand Down Expand Up @@ -966,15 +1001,15 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config) noexcept {
}

// Output vertex color if necessary
if (UsePerPixelLighting) {
if (config.enhancedLighting) {
if ((cc.lightingEnabled && cc.ambSrc == GX_SRC_VTX) || cc.matSrc == GX_SRC_VTX ||
(cca.lightingEnabled && cca.ambSrc == GX_SRC_VTX) || cca.matSrc == GX_SRC_VTX) {
vtxOutAttrs += fmt::format("\n @location({}) clr{}: vec4f,", vtxOutIdx++, i);
vtxXfrAttrs += fmt::format("\n out.clr{} = {};", i, vtx_attr(config, static_cast<GXAttr>(GX_VA_CLR0 + i)));
}
}

if (UsePerPixelLighting) {
if (config.enhancedLighting) {
fragmentFnPre += fmt::format("\n var rast{}: vec4f;", i);
fragmentFnPre += lighting_func(config, cc, i, false);
fragmentFnPre += lighting_func(config, cca, i, true);
Expand Down
11 changes: 11 additions & 0 deletions lib/gx/shader_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,13 @@ ShaderInfo build_shader_info(const ShaderConfig& config) noexcept {
}
}
if (info.lightingEnabled) {
info.enhancedLighting = config.enhancedLighting;
// Lights + light state for all channels
info.uniformSize += 16 + sizeof(Light) * GX::MaxLights;
if (info.enhancedLighting) {
// specular_intensity, rim_intensity, ambient_multiplier, diffuse_multiplier
info.uniformSize += 16;
}
}
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
if (info.sampledColorChannels.test(i)) {
Expand Down Expand Up @@ -406,6 +411,12 @@ gfx::Range build_uniform(const ShaderInfo& info, u32 vtxStart, const BindGroupRa
for (int i = 0; i < 4; ++i) {
buf.append<u32>(g_gxState.colorChannelState[i].lightMask.to_ulong());
}
if (info.enhancedLighting) {
buf.append<f32>(g_specularIntensity);
buf.append<f32>(g_rimIntensity);
buf.append<f32>(g_ambientMultiplier);
buf.append<f32>(g_diffuseMultiplier);
}
}
for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
if (!info.sampledColorChannels.test(i)) {
Expand Down
Loading