feat(atmospherics): Add sky color configuration and apply in rendering

This commit is contained in:
2026-01-06 01:07:26 +00:00
parent 62a3d26279
commit 1f3e48ae27
5 changed files with 76 additions and 5 deletions

View File

@@ -64,6 +64,7 @@
"ambient_strength": 0.01,
"fog_density": 0.003,
"fog_color": [0.05, 0.05, 0.08],
"sky_color": [0.04, 0.05, 0.08],
"gamma": 2.2,
"exposure": 1.0,
"enable_tone_mapping": true,

View File

@@ -9,6 +9,7 @@ local cube_mesh_info = {
local cube_vertices = {}
local cube_indices = {}
local cube_indices_double_sided = {}
local skybox_color = {0.04, 0.05, 0.08}
local function build_double_sided_indices(indices)
local doubled = {}
@@ -224,6 +225,29 @@ if cube_mesh_info.loaded then
end
end
local function resolve_color3(value, fallback)
if type(value) == "table" then
local r = tonumber(value[1])
local g = tonumber(value[2])
local b = tonumber(value[3])
if r and g and b then
return {r, g, b}
end
end
return {fallback[1], fallback[2], fallback[3]}
end
local function apply_skybox_color_from_config()
if type(config) ~= "table" then
return
end
local atmospherics = config.atmospherics
if type(atmospherics) ~= "table" then
return
end
skybox_color = resolve_color3(atmospherics.sky_color, skybox_color)
end
local function build_static_shader_variants()
local fallback_vertex_source = [[
#version 450
@@ -294,6 +318,10 @@ void main() {
vertex_source = fallback_vertex_source,
fragment_source = fallback_fragment_source,
},
skybox = {
vertex_source = fallback_vertex_source,
fragment_source = fallback_fragment_source,
},
}
end
@@ -306,19 +334,36 @@ local function count_shader_variants(variants)
end
local function build_shader_variants()
apply_skybox_color_from_config()
local ok, toolkit = pcall(require, "shader_toolkit")
if not ok then
log_debug("Shader toolkit unavailable: %s", tostring(toolkit))
return build_static_shader_variants()
end
local output_mode = "source"
local compile = false
local ok_generate, generated = pcall(toolkit.generate_cube_demo_variants,
{compile = false, output_mode = "source"})
{compile = compile, output_mode = output_mode})
if not ok_generate then
log_debug("Shader generation failed: %s", tostring(generated))
return build_static_shader_variants()
end
local ok_skybox, skybox_variant = pcall(toolkit.generate_variant, {
key = "skybox",
template = "solid_color",
output_mode = output_mode,
compile = compile,
parameters = {color = skybox_color},
})
if ok_skybox then
generated.skybox = skybox_variant
else
log_debug("Skybox shader generation failed: %s", tostring(skybox_variant))
end
log_debug("Generated %d shader variants", count_shader_variants(generated))
return generated
end
@@ -642,6 +687,22 @@ local function create_static_cube(position, scale, color, shader_key)
}
end
local function create_skybox()
local skybox_scale = camera.far * 0.85
local function compute_model_matrix()
local translation = math3d.translation(camera.position[1], camera.position[2], camera.position[3])
local scaling = scale_matrix(skybox_scale, skybox_scale, skybox_scale)
return math3d.multiply(translation, scaling)
end
return {
vertices = apply_color_to_vertices(skybox_color),
indices = (#cube_indices_double_sided > 0) and cube_indices_double_sided or cube_indices,
compute_model_matrix = compute_model_matrix,
shader_key = "skybox",
}
end
local function create_spinning_cube()
log_debug("Spinning cube shader=default (rainbow wrap)")
local function compute_model_matrix(time)
@@ -830,6 +891,7 @@ end
function get_scene_objects()
local objects = {}
objects[#objects + 1] = create_skybox()
for i = 1, #room_objects do
objects[#objects + 1] = room_objects[i]
end

View File

@@ -352,6 +352,7 @@ RuntimeConfig JsonConfigService::LoadFromJson(std::shared_ptr<ILogger> logger,
readFloat("ambient_strength", config.atmospherics.ambientStrength);
readFloat("fog_density", config.atmospherics.fogDensity);
readFloatArray3("fog_color", config.atmospherics.fogColor);
readFloatArray3("sky_color", config.atmospherics.skyColor);
readFloat("gamma", config.atmospherics.gamma);
readFloat("exposure", config.atmospherics.exposure);
readBool("enable_tone_mapping", config.atmospherics.enableToneMapping);

View File

@@ -126,10 +126,19 @@ void RenderCommandService::RecordCommands(uint32_t imageIndex,
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = extent;
const auto& config = configService_->GetConfig();
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = {{0.1f, 0.1f, 0.15f, 1.0f}}; // Color clear
const auto& skyColor = config.atmospherics.skyColor;
clearValues[0].color = {{skyColor[0], skyColor[1], skyColor[2], 1.0f}}; // Skybox clear
clearValues[1].depthStencil = {1.0f, 0}; // Depth clear
if (logger_) {
logger_->Trace("RenderCommandService", "RecordCommands",
"clearColor=" + std::to_string(skyColor[0]) + "," +
std::to_string(skyColor[1]) + "," +
std::to_string(skyColor[2]));
}
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
@@ -181,9 +190,6 @@ void RenderCommandService::RecordCommands(uint32_t imageIndex,
// For PBR shaders, populate extended push constants
if (command.shaderKey.find("pbr") != std::string::npos) {
// Get atmospherics config
auto config = configService_->GetConfig();
// For now, use identity for view and proj (since viewProj is already combined)
// In a full implementation, we'd need separate view/proj matrices
pushConstants.view = {1.0f, 0.0f, 0.0f, 0.0f,

View File

@@ -70,6 +70,7 @@ struct AtmosphericsConfig {
float ambientStrength = 0.01f;
float fogDensity = 0.003f;
std::array<float, 3> fogColor = {0.05f, 0.05f, 0.08f};
std::array<float, 3> skyColor = {0.1f, 0.1f, 0.15f};
float gamma = 2.2f;
float exposure = 1.0f;
bool enableToneMapping = true;