Fix hemisphere light orientation when the top is set on Z+ (#7708)

This commit is contained in:
D8H
2025-07-10 12:09:18 +02:00
committed by GitHub
parent 307c92991c
commit 3592fb7e62
4 changed files with 69 additions and 58 deletions

View File

@@ -18,19 +18,18 @@ namespace gdjs {
return new gdjs.PixiFiltersTools.EmptyFilter();
}
return new (class implements gdjs.PixiFiltersTools.Filter {
private _light: THREE.DirectionalLight;
private _isEnabled: boolean = false;
private _top: string = 'Y-';
private _top: string = 'Z+';
private _elevation: float = 45;
private _rotation: float = 0;
private _shadowMapDirty = true;
private _shadowMapSize: float = 1024;
private _minimumShadowBias: float = 0;
private _shadowCameraDirty = true;
private _distanceFromCamera: float = 1500;
private _frustumSize: float = 4000;
private _isEnabled: boolean = false;
private _light: THREE.DirectionalLight;
private _shadowMapDirty = true;
private _shadowCameraDirty = true;
private _shadowCameraHelper: THREE.CameraHelper | null;
constructor() {

View File

@@ -18,18 +18,15 @@ namespace gdjs {
return new gdjs.PixiFiltersTools.EmptyFilter();
}
return new (class implements gdjs.PixiFiltersTools.Filter {
light: THREE.HemisphereLight;
rotationObject: THREE.Group;
_top: string = 'Z+';
_elevation: float = 90;
_rotation: float = 0;
_isEnabled: boolean = false;
top: string = 'Y-';
elevation: float = 45;
rotation: float = 0;
_light: THREE.HemisphereLight;
constructor() {
this.light = new THREE.HemisphereLight();
this.light.position.set(1, 0, 0);
this.rotationObject = new THREE.Group();
this.rotationObject.add(this.light);
this._light = new THREE.HemisphereLight();
this.updateRotation();
}
@@ -54,7 +51,7 @@ namespace gdjs {
if (!scene) {
return false;
}
scene.add(this.rotationObject);
scene.add(this._light);
this._isEnabled = true;
return true;
}
@@ -66,96 +63,106 @@ namespace gdjs {
if (!scene) {
return false;
}
scene.remove(this.rotationObject);
scene.remove(this._light);
this._isEnabled = false;
return true;
}
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {
if (parameterName === 'intensity') {
this.light.intensity = value;
this._light.intensity = value;
} else if (parameterName === 'elevation') {
this.elevation = value;
this._elevation = value;
this.updateRotation();
} else if (parameterName === 'rotation') {
this.rotation = value;
this._rotation = value;
this.updateRotation();
}
}
getDoubleParameter(parameterName: string): number {
if (parameterName === 'intensity') {
return this.light.intensity;
return this._light.intensity;
} else if (parameterName === 'elevation') {
return this.elevation;
return this._elevation;
} else if (parameterName === 'rotation') {
return this.rotation;
return this._rotation;
}
return 0;
}
updateStringParameter(parameterName: string, value: string): void {
if (parameterName === 'skyColor') {
this.light.color = new THREE.Color(
this._light.color = new THREE.Color(
gdjs.rgbOrHexStringToNumber(value)
);
}
if (parameterName === 'groundColor') {
this.light.groundColor = new THREE.Color(
this._light.groundColor = new THREE.Color(
gdjs.rgbOrHexStringToNumber(value)
);
}
if (parameterName === 'top') {
this.top = value;
this._top = value;
this.updateRotation();
}
}
updateColorParameter(parameterName: string, value: number): void {
if (parameterName === 'skyColor') {
this.light.color.setHex(value);
this._light.color.setHex(value);
}
if (parameterName === 'groundColor') {
this.light.groundColor.setHex(value);
this._light.groundColor.setHex(value);
}
}
getColorParameter(parameterName: string): number {
if (parameterName === 'skyColor') {
return this.light.color.getHex();
return this._light.color.getHex();
}
if (parameterName === 'groundColor') {
return this.light.groundColor.getHex();
return this._light.groundColor.getHex();
}
return 0;
}
updateBooleanParameter(parameterName: string, value: boolean): void {}
updateRotation() {
if (this.top === 'Z+') {
// 0° is a light from the right of the screen.
this.rotationObject.rotation.z = gdjs.toRad(this.rotation);
this.rotationObject.rotation.y = -gdjs.toRad(this.elevation);
if (this._top === 'Y-') {
// `rotation` at 0° becomes a light from Z+.
this._light.position.set(
Math.cos(gdjs.toRad(-this._rotation + 90)) *
Math.cos(gdjs.toRad(this._elevation)),
-Math.sin(gdjs.toRad(this._elevation)),
Math.sin(gdjs.toRad(-this._rotation + 90)) *
Math.cos(gdjs.toRad(this._elevation))
);
} else {
// 0° becomes a light from Z+.
this.rotationObject.rotation.y = gdjs.toRad(this.rotation - 90);
this.rotationObject.rotation.z = -gdjs.toRad(this.elevation);
// `rotation` at 0° is a light from the right of the screen.
this._light.position.set(
Math.cos(gdjs.toRad(this._rotation)) *
Math.cos(gdjs.toRad(this._elevation)),
Math.sin(gdjs.toRad(this._rotation)) *
Math.cos(gdjs.toRad(this._elevation)),
Math.sin(gdjs.toRad(this._elevation))
);
}
}
getNetworkSyncData(): HemisphereLightFilterNetworkSyncData {
return {
i: this.light.intensity,
sc: this.light.color.getHex(),
gc: this.light.groundColor.getHex(),
e: this.elevation,
r: this.rotation,
t: this.top,
i: this._light.intensity,
sc: this._light.color.getHex(),
gc: this._light.groundColor.getHex(),
e: this._elevation,
r: this._rotation,
t: this._top,
};
}
updateFromNetworkSyncData(
syncData: HemisphereLightFilterNetworkSyncData
): void {
this.light.intensity = syncData.i;
this.light.color.setHex(syncData.sc);
this.light.groundColor.setHex(syncData.gc);
this.elevation = syncData.e;
this.rotation = syncData.r;
this.top = syncData.t;
this._light.intensity = syncData.i;
this._light.color.setHex(syncData.sc);
this._light.groundColor.setHex(syncData.gc);
this._elevation = syncData.e;
this._rotation = syncData.r;
this._top = syncData.t;
this.updateRotation();
}
})();

View File

@@ -1916,11 +1916,11 @@ module.exports = {
.setType('number');
properties
.getOrCreate('top')
.setValue('Y-')
.setValue('Z+')
.setLabel(_('3D world top'))
.setType('choice')
.addExtraInfo('Y-')
.addExtraInfo('Z+')
.addExtraInfo('Y-')
.setGroup(_('Orientation'));
properties
.getOrCreate('elevation')
@@ -1974,6 +1974,7 @@ module.exports = {
.setValue('1500')
.setLabel(_("Distance from layer's camera"))
.setType('number')
.setGroup(_('Shadows'))
.setAdvanced(true);
}
{
@@ -2006,11 +2007,11 @@ module.exports = {
.setType('number');
properties
.getOrCreate('top')
.setValue('Y-')
.setValue('Z+')
.setLabel(_('3D world top'))
.setType('choice')
.addExtraInfo('Y-')
.addExtraInfo('Z+')
.addExtraInfo('Y-')
.setGroup(_('Orientation'));
properties
.getOrCreate('elevation')

View File

@@ -46,10 +46,14 @@ export const addDefaultLightToLayer = (layer: gdLayer): void => {
const ambientLight = layer
.getEffects()
.insertNewEffect('3D Ammbient Light', 0);
ambientLight.setEffectType('Scene3D::AmbientLight');
ambientLight.setStringParameter('color', '255;255;255');
ambientLight.setDoubleParameter('intensity', 0.25);
.insertNewEffect('3D Ambient Hemisphere Light', 0);
ambientLight.setEffectType('Scene3D::HemisphereLight');
ambientLight.setStringParameter('skyColor', '255;255;255');
ambientLight.setStringParameter('groundColor', '127;127;127');
ambientLight.setDoubleParameter('intensity', 0.33);
ambientLight.setStringParameter('top', 'Z+');
ambientLight.setDoubleParameter('elevation', 40);
ambientLight.setDoubleParameter('rotation', 300);
};
export const addDefaultLightToAllLayers = (layout: gdLayout): void => {