feat(web): wire Blender world probe 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 20:32:02 +08:00
parent b15ac3770a
commit 6692739cfe
38 changed files with 1976 additions and 20 deletions

View File

@@ -5199,6 +5199,10 @@ json scene_ir_from_blend(const ParsedBlend &blend,
world["sunShadowMaximumResolution"] = read_float(*blend.sdna, element, "sun_shadow_maximum_resolution").value_or(0.001f);
world["sunShadowJitterOverblur"] = read_float(*blend.sdna, element, "sun_shadow_jitter_overblur").value_or(10.0f);
world["sunShadowFilterRadius"] = read_float(*blend.sdna, element, "sun_shadow_filter_radius").value_or(1.0f);
world["probeResolution"] = read_integer(*blend.sdna, element, "probe_resolution").value_or(10);
const int64_t world_flags = read_integer(*blend.sdna, element, "flag").value_or(0);
world["useSunShadow"] = (world_flags & (1 << 4)) != 0;
world["useSunShadowJitter"] = (world_flags & (1 << 5)) != 0;
if (const std::optional<uint64_t> lightgroup_pointer = read_pointer(*blend.sdna, element, "lightgroup")) {
if (const std::optional<ElementRef> membership = element_for_pointer(blend, *lightgroup_pointer)) {
const std::string lightgroup_name = read_string(*blend.sdna, *membership, "name");

View File

@@ -5631,6 +5631,35 @@ bool web_engine_blend_main_set_world_lighting_controls(WebBlendMainState *state,
return true;
}
bool web_engine_blend_main_set_world_probe_controls(WebBlendMainState *state,
const char *target_id,
const int probe_resolution,
const bool use_sun_shadow,
const bool use_sun_shadow_jitter,
std::string &error)
{
if (state == nullptr || state->main == nullptr || target_id == nullptr) {
error = "RENDER_PROPERTY_INVALID: world probe target is missing";
return false;
}
World *world = find_world(state->main, target_id);
if (world == nullptr || world->id.lib != nullptr) {
error = "LINKED_DATA_MUTATION_BLOCKED: World is not editable";
return false;
}
if (probe_resolution < LIGHT_PROBE_RESOLUTION_128 || probe_resolution > LIGHT_PROBE_RESOLUTION_4096) {
error = "RENDER_PROPERTY_INVALID: world probe resolution is unsupported";
return false;
}
world->probe_resolution = eLightProbeResolution(probe_resolution);
if (use_sun_shadow) world->flag |= WO_USE_SUN_SHADOW;
else world->flag &= ~WO_USE_SUN_SHADOW;
if (use_sun_shadow_jitter) world->flag |= WO_USE_SUN_SHADOW_JITTER;
else world->flag &= ~WO_USE_SUN_SHADOW_JITTER;
world->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,
@@ -5952,7 +5981,7 @@ bool web_engine_blend_main_set_render_properties(WebBlendMainState *state,
if (strncmp(target_id, "world:", 6) == 0) {
World *world = find_world(state->main, target_id);
if (world == nullptr || world->id.lib != nullptr ||
!reject_unknown({"color", "exposure", "ambientOcclusionDistance", "ambientOcclusionEnergy", "sunThreshold", "sunAngle", "sunShadowMaximumResolution", "sunShadowJitterOverblur", "sunShadowFilterRadius", "mist"}) ||
!reject_unknown({"color", "exposure", "ambientOcclusionDistance", "ambientOcclusionEnergy", "sunThreshold", "sunAngle", "sunShadowMaximumResolution", "sunShadowJitterOverblur", "sunShadowFilterRadius", "probeResolution", "useSunShadow", "useSunShadowJitter", "mist"}) ||
!read_color("color", &world->horr) ||
!read_float("exposure", -20.0f, 20.0f, world->exposure))
{
@@ -5978,6 +6007,27 @@ bool web_engine_blend_main_set_render_properties(WebBlendMainState *state,
if (ao_distance < 0.0f || ao_energy < 0.0f || sun_threshold < 0.0f || sun_angle < 0.0f || sun_shadow_maximum_resolution < 0.0f || sun_shadow_jitter_overblur < 0.0f || sun_shadow_filter_radius < 0.0f ||
!web_engine_blend_main_set_world_lighting_controls(state, target_id, ao_distance, ao_energy, sun_threshold, sun_angle, sun_shadow_maximum_resolution, sun_shadow_jitter_overblur, sun_shadow_filter_radius, error)) return false;
}
if (properties.contains("probeResolution") || properties.contains("useSunShadow") || properties.contains("useSunShadowJitter")) {
int probe_resolution = int(world->probe_resolution);
if (properties.contains("probeResolution")) {
if (!properties["probeResolution"].is_number_integer()) {
error = "RENDER_PROPERTY_INVALID: probeResolution must be an integer";
return false;
}
probe_resolution = properties["probeResolution"].get<int>();
}
bool use_sun_shadow = (world->flag & WO_USE_SUN_SHADOW) != 0;
bool use_sun_shadow_jitter = (world->flag & WO_USE_SUN_SHADOW_JITTER) != 0;
if (properties.contains("useSunShadow")) {
if (!properties["useSunShadow"].is_boolean()) { error = "RENDER_PROPERTY_INVALID: useSunShadow must be boolean"; return false; }
use_sun_shadow = properties["useSunShadow"].get<bool>();
}
if (properties.contains("useSunShadowJitter")) {
if (!properties["useSunShadowJitter"].is_boolean()) { error = "RENDER_PROPERTY_INVALID: useSunShadowJitter must be boolean"; return false; }
use_sun_shadow_jitter = properties["useSunShadowJitter"].get<bool>();
}
if (!web_engine_blend_main_set_world_probe_controls(state, target_id, probe_resolution, use_sun_shadow, use_sun_shadow_jitter, error)) return false;
}
if (properties.contains("mist")) {
const json &mist = properties["mist"];
if (!mist.is_object() || mist.empty()) {

View File

@@ -563,6 +563,12 @@ bool web_engine_blend_main_set_world_lighting_controls(WebBlendMainState *state,
float sun_shadow_jitter_overblur,
float sun_shadow_filter_radius,
std::string &error);
bool web_engine_blend_main_set_world_probe_controls(WebBlendMainState *state,
const char *target_id,
int probe_resolution,
bool use_sun_shadow,
bool use_sun_shadow_jitter,
std::string &error);
bool web_engine_blend_main_set_scene_properties(WebBlendMainState *state,
const char *target_id,
const char *properties_json,