diff --git a/src/editor/InspectorPanel.jsx b/src/editor/InspectorPanel.jsx
index 35d68b1..f450038 100644
--- a/src/editor/InspectorPanel.jsx
+++ b/src/editor/InspectorPanel.jsx
@@ -526,11 +526,73 @@ const InspectorPanel = ({
style={{ width: '100%' }}
/>
+
+
+ Заливка теней
+ {(selection.sceneAmbient ?? 0.3).toFixed(2)}
+
+
props.onSetLightingProps?.({ sceneAmbient: parseFloat(e.target.value) })}
+ style={{ width: '100%' }}
+ />
+
+ Подсветка теней — цвет в затенённых гранях. 0 = чёрные тени, 1 = плоско.
+
+
+
Цветокоррекция
+
+
+ Экспозиция
+ {(selection.exposure ?? 1.0).toFixed(2)}
+
+
props.onSetLightingProps?.({ exposure: parseFloat(e.target.value) })}
+ style={{ width: '100%' }}
+ />
+
+ Общая яркость. <1 = темнее, >1 = светлее.
+
+
+
+
+ Контраст
+ {(selection.contrast ?? 1.0).toFixed(2)}
+
+
props.onSetLightingProps?.({ contrast: parseFloat(e.target.value) })}
+ style={{ width: '100%' }}
+ />
+
+
+
+ Насыщенность
+ {(selection.saturation ?? 1.0).toFixed(2)}
+
+
props.onSetLightingProps?.({ saturation: parseFloat(e.target.value) })}
+ style={{ width: '100%' }}
+ />
+
+ 0 = чёрно-белое, 1 = норма, 2 = очень сочно.
+
+
+
+
{/* Туман */}
Туман
diff --git a/src/editor/engine/BabylonScene.js b/src/editor/engine/BabylonScene.js
index 175c430..dc89f9a 100644
--- a/src/editor/engine/BabylonScene.js
+++ b/src/editor/engine/BabylonScene.js
@@ -37,6 +37,7 @@ import {
Ray,
PointerEventTypes,
Tools as BabylonTools,
+ ColorCurves,
} from '@babylonjs/core';
import { PlacementManager } from './PlacementManager';
import { ShopInventoryUi } from './ShopInventoryUi';
@@ -1885,9 +1886,41 @@ export class BabylonScene {
}
if (typeof patch.sunIntensity === 'number' && this._sunLight) {
this._sunLight.intensity = Math.max(0, patch.sunIntensity);
+ this._sunIntensity = patch.sunIntensity;
}
if (typeof patch.hemiIntensity === 'number' && this._hemiLight) {
this._hemiLight.intensity = Math.max(0, patch.hemiIntensity);
+ this._hemiIntensity = patch.hemiIntensity;
+ }
+ // Окружающий свет (scene.ambientColor) — отдельный множитель.
+ // Применяется ко всем материалам через ambient*ambient.
+ if (typeof patch.sceneAmbient === 'number') {
+ const v = Math.max(0, Math.min(1, patch.sceneAmbient));
+ this.scene.ambientColor = new Color3(v, v, v);
+ this._sceneAmbient = v;
+ }
+ // Цветокоррекция — экспозиция, контраст, насыщенность через
+ // imageProcessingConfiguration (включает HDR pipeline).
+ if (typeof patch.exposure === 'number' || typeof patch.contrast === 'number'
+ || typeof patch.saturation === 'number') {
+ const ipc = this.scene.imageProcessingConfiguration;
+ ipc.isEnabled = true;
+ if (typeof patch.exposure === 'number') {
+ ipc.exposure = Math.max(0.1, Math.min(3, patch.exposure));
+ this._exposure = ipc.exposure;
+ }
+ if (typeof patch.contrast === 'number') {
+ ipc.contrast = Math.max(0.5, Math.min(2.5, patch.contrast));
+ this._contrast = ipc.contrast;
+ }
+ if (typeof patch.saturation === 'number') {
+ // colorCurves для saturation (стандартный Babylon приём)
+ if (!ipc.colorCurves) ipc.colorCurves = new ColorCurves();
+ const s = Math.max(-100, Math.min(100, (patch.saturation - 1) * 100));
+ ipc.colorCurves.globalSaturation = s;
+ ipc.colorCurvesEnabled = true;
+ this._saturation = patch.saturation;
+ }
}
if (this.environment && typeof this.environment.setFog === 'function') {
// Текущие значения берём из Environment, поверх накладываем patch
diff --git a/src/editor/engine/PrimitiveManager.js b/src/editor/engine/PrimitiveManager.js
index d0471ad..8d7d899 100644
--- a/src/editor/engine/PrimitiveManager.js
+++ b/src/editor/engine/PrimitiveManager.js
@@ -506,11 +506,9 @@ export class PrimitiveManager {
_applyMaterial(mesh, typeDef, color, material, textureUrl) {
const matName = `${mesh.name}_mat`;
const mat = new StandardMaterial(matName, this.scene);
- const dc = Color3.FromHexString(color || '#888888');
- mat.diffuseColor = dc;
- // ambient = 40% от цвета. Roblox-look: тень окрашена, но не
- // суммируется с прямым светом в пересвет. Белые остаются белыми.
- mat.ambientColor = new Color3(dc.r * 0.4, dc.g * 0.4, dc.b * 0.4);
+ mat.diffuseColor = Color3.FromHexString(color || '#888888');
+ // ambient = default (0,0,0). Освещение настраивается через
+ // глобальную панель «Свет и атмосфера» (sun/hemi/saturation).
// Если задан textureUrl — подгружаем PNG как diffuseTexture. Это
// используется для GD-скинов куба (например /gd/skins/cube_smile.png).
diff --git a/src/editor/engine/SelectionManager.js b/src/editor/engine/SelectionManager.js
index f20b397..834197f 100644
--- a/src/editor/engine/SelectionManager.js
+++ b/src/editor/engine/SelectionManager.js
@@ -282,6 +282,11 @@ export class SelectionManager {
fogColor: env ? `#${[env.fogColor?.[0] ?? 0.7, env.fogColor?.[1] ?? 0.8, env.fogColor?.[2] ?? 0.9].map(c => Math.round(Math.max(0, Math.min(1, c)) * 255).toString(16).padStart(2, '0')).join('')}` : '#b0c8e6',
shadowQuality: this._scene3d.getShadowQuality?.() || 'soft',
ssaoEnabled: this._scene3d.getSsaoEnabled?.() || false,
+ // Новые: глобальный ambient + image processing
+ sceneAmbient: this._scene3d._sceneAmbient ?? 0.3,
+ exposure: this._scene3d._exposure ?? 1.0,
+ contrast: this._scene3d._contrast ?? 1.0,
+ saturation: this._scene3d._saturation ?? 1.0,
};
this._notifyChange();
}