feat(web): wire Blender light shadow controls
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-30 18:56:28 +08:00
parent 8bc5d61b75
commit 4ce5581bc3
46 changed files with 2018 additions and 49 deletions

View File

@@ -5167,6 +5167,10 @@ json scene_ir_from_blend(const ParsedBlend &blend,
{"specularFactor", read_float(*blend.sdna, element, "spec_fac").value_or(1.0f)},
{"transmissionFactor", read_float(*blend.sdna, element, "transmission_fac").value_or(1.0f)},
{"volumeFactor", read_float(*blend.sdna, element, "volume_fac").value_or(1.0f)},
{"attenuationDistance", read_float(*blend.sdna, element, "att_dist").value_or(40.0f)},
{"shadowFilterRadius", read_float(*blend.sdna, element, "shadow_filter_radius").value_or(1.0f)},
{"shadowMaximumResolution", read_float(*blend.sdna, element, "shadow_maximum_resolution").value_or(0.001f)},
{"shadowJitterOverblur", read_float(*blend.sdna, element, "shadow_jitter_overblur").value_or(10.0f)},
{"areaSize", read_float(*blend.sdna, element, "area_size").value_or(0.25f)},
{"areaSizeY", read_float(*blend.sdna, element, "area_sizey").value_or(0.25f)},
{"areaSpread", read_float(*blend.sdna, element, "area_spread").value_or(3.14159265f)},

View File

@@ -5483,6 +5483,38 @@ bool web_engine_blend_main_set_light_contribution_factors(WebBlendMainState *sta
return true;
}
bool web_engine_blend_main_set_light_shadow_controls(WebBlendMainState *state,
const char *target_id,
const float attenuation_distance,
const float shadow_filter_radius,
const float shadow_maximum_resolution,
const float shadow_jitter_overblur,
std::string &error)
{
if (state == nullptr || state->main == nullptr || target_id == nullptr) {
error = "RENDER_PROPERTY_INVALID: light shadow control target is missing";
return false;
}
Light *light = find_light(state->main, target_id);
if (light == nullptr || !ensure_single_user_data(state->main, &light->id, error)) {
if (error.empty()) error = "RENDER_PROPERTY_INVALID: light was not found";
return false;
}
const float values[] = {attenuation_distance, shadow_filter_radius, shadow_maximum_resolution, shadow_jitter_overblur};
if (!std::all_of(std::begin(values), std::end(values), [](const float value) { return std::isfinite(value) && value >= 0.0f; }) ||
shadow_maximum_resolution < 0.0000001f || shadow_maximum_resolution > 1.0e9f ||
attenuation_distance > 1.0e9f || shadow_filter_radius > 1.0e9f || shadow_jitter_overblur > 1.0e9f) {
error = "RENDER_PROPERTY_INVALID: light shadow control is outside the bounded range";
return false;
}
light->att_dist = attenuation_distance;
light->shadow_filter_radius = shadow_filter_radius;
light->shadow_maximum_resolution = shadow_maximum_resolution;
light->shadow_jitter_overblur = shadow_jitter_overblur;
light->id.recalc |= ID_RECALC_PARAMETERS;
return true;
}
bool web_engine_blend_main_set_render_properties(WebBlendMainState *state,
const char *target_id,
const char *properties_json,
@@ -5679,7 +5711,7 @@ bool web_engine_blend_main_set_render_properties(WebBlendMainState *state,
if (strncmp(target_id, "light:", 6) == 0) {
Light *light = find_light(state->main, target_id);
if (light == nullptr || !ensure_single_user_data(state->main, &light->id, error)) return false;
if (!reject_unknown({"type", "areaShape", "diffuseFactor", "specularFactor", "transmissionFactor", "volumeFactor", "color", "energy", "exposure", "temperature", "useTemperature",
if (!reject_unknown({"type", "areaShape", "diffuseFactor", "specularFactor", "transmissionFactor", "volumeFactor", "attenuationDistance", "shadowFilterRadius", "shadowMaximumResolution", "shadowJitterOverblur", "color", "energy", "exposure", "temperature", "useTemperature",
"castsShadow", "radius", "spotAngle", "spotBlend", "areaSize",
"areaSizeY", "areaSpread", "sunAngle"}))
{
@@ -5716,6 +5748,22 @@ bool web_engine_blend_main_set_render_properties(WebBlendMainState *state,
if (diffuse < 0.0f || specular < 0.0f || transmission < 0.0f || volume < 0.0f ||
!web_engine_blend_main_set_light_contribution_factors(state, target_id, diffuse, specular, transmission, volume, error)) return false;
}
if (properties.contains("attenuationDistance") || properties.contains("shadowFilterRadius") || properties.contains("shadowMaximumResolution") || properties.contains("shadowJitterOverblur")) {
const auto shadow_value = [&](const char *key, const float current) {
if (!properties.contains(key)) return current;
if (!properties[key].is_number()) {
error = std::string("RENDER_PROPERTY_INVALID: ") + key + " must be numeric";
return -1.0f;
}
return properties[key].get<float>();
};
const float attenuation = shadow_value("attenuationDistance", light->att_dist);
const float filter_radius = shadow_value("shadowFilterRadius", light->shadow_filter_radius);
const float maximum_resolution = shadow_value("shadowMaximumResolution", light->shadow_maximum_resolution);
const float jitter_overblur = shadow_value("shadowJitterOverblur", light->shadow_jitter_overblur);
if (attenuation < 0.0f || filter_radius < 0.0f || maximum_resolution < 0.0f || jitter_overblur < 0.0f ||
!web_engine_blend_main_set_light_shadow_controls(state, target_id, attenuation, filter_radius, maximum_resolution, jitter_overblur, error)) return false;
}
if (!read_color("color", &light->r) ||
!read_float("energy", 0.0f, 1.0e9f, light->energy) ||
!read_float("exposure", -20.0f, 20.0f, light->exposure) ||

View File

@@ -531,6 +531,13 @@ bool web_engine_blend_main_set_light_contribution_factors(WebBlendMainState *sta
float transmission_factor,
float volume_factor,
std::string &error);
bool web_engine_blend_main_set_light_shadow_controls(WebBlendMainState *state,
const char *target_id,
float attenuation_distance,
float shadow_filter_radius,
float shadow_maximum_resolution,
float shadow_jitter_overblur,
std::string &error);
bool web_engine_blend_main_set_scene_properties(WebBlendMainState *state,
const char *target_id,
const char *properties_json,