Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
46c845f
Build Three.js as UMD
D8H Jul 15, 2026
01a75d3
Upgrade to Three.js 0.161.0
D8H Jul 15, 2026
88d7869
Upgrade to Three.js 0.162.0
D8H Jul 16, 2026
76b58d3
Upgrade to Three.js 0.164.0
D8H Jul 16, 2026
fe09aa4
Upgrade to Three.js 0.165.0
D8H Jul 16, 2026
7341cc6
Add a 3D renderer world scale property
D8H Jul 16, 2026
65391a5
Fix the patch
D8H Jul 16, 2026
7a0278a
Upgrade to Three.js 0.167.0
D8H Jul 16, 2026
e82bea8
Upgrade to Three.js 0.168.0
D8H Jul 16, 2026
267dba5
Upgrade to Three.js 0.169.0
D8H Jul 16, 2026
f84ad57
Upgrade to Three.js 0.174.0
D8H Jul 16, 2026
52bdc74
Upgrade to Three.js 0.175.0
D8H Jul 16, 2026
7c8b31b
Upgrade to Three.js 0.176.0
D8H Jul 16, 2026
87ab6ba
Upgrade to Three.js 0.177.0
D8H Jul 16, 2026
af4e296
Upgrade to Three.js 0.180.0
D8H Jul 16, 2026
bf86fe5
Upgrade to Three.js 0.181.0
D8H Jul 16, 2026
310d3c8
Upgrade to Three.js 0.185.1
D8H Jul 16, 2026
036fbf4
Update all addon sources
D8H Jul 16, 2026
c6ed062
Upgrade newIDE to Three.js 0.185.1
D8H Jul 17, 2026
c8c78e2
Use the same default light angle as the 2D editor
D8H Jul 17, 2026
a97d085
Rotate the light the other way
D8H Jul 17, 2026
61152ae
Remove deprecated attribute
D8H Jul 17, 2026
3f12413
Fix object dragging in the 3D editor
D8H Jul 20, 2026
940be8f
Fix fog world scale
D8H Jul 20, 2026
96db58b
Fix camera look at actions
D8H Jul 21, 2026
f67d8e6
Fix near and far planes
D8H Jul 21, 2026
d421309
Fix shadows
D8H Jul 21, 2026
50c3e07
Upgrade Three.js in package-lock.json
D8H Jul 21, 2026
788a250
Fix directional light.
D8H Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Core/GDCore/Project/Layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ void Layout::SerializeTo(SerializerElement& element) const {
element.SetAttribute("resourcesUnloading", resourcesUnloading);
element.SetAttribute("disableInputWhenNotFocused",
disableInputWhenNotFocused);
element.SetAttribute("renderer3DWorldScale", renderer3DWorldScale);

editorSettings.SerializeTo(element.AddChild("uiSettings"));

Expand Down Expand Up @@ -316,6 +317,8 @@ void Layout::UnserializeFrom(gd::Project& project,
element.GetStringAttribute("resourcesUnloading", "inherit");
disableInputWhenNotFocused =
element.GetBoolAttribute("disableInputWhenNotFocused");
renderer3DWorldScale =
element.GetDoubleAttribute("renderer3DWorldScale", 100);

editorSettings.UnserializeFrom(
element.GetChild("uiSettings", 0, "UISettings"));
Expand Down Expand Up @@ -404,6 +407,7 @@ void Layout::Init(const Layout& other) {
resourcesPreloading = other.resourcesPreloading;
resourcesUnloading = other.resourcesUnloading;
disableInputWhenNotFocused = other.disableInputWhenNotFocused;
renderer3DWorldScale = other.renderer3DWorldScale;
initialInstances = other.initialInstances;
layers = other.layers;
variables = other.GetVariables();
Expand Down
13 changes: 13 additions & 0 deletions Core/GDCore/Project/Layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,18 @@ class GD_CORE_API Layout {
* `inherit` (default).
*/
const gd::String& GetResourcesUnloading() const { return resourcesUnloading; }

/**
* Get the world scale used by the 3D renderer.
*/
const double GetRenderer3DWorldScale() const { return renderer3DWorldScale; };

/**
* Set the world scale used by the 3D renderer.
*/
void SetRenderer3DWorldScale(double worldScale) {
renderer3DWorldScale = worldScale;
};
///@}

/** \name Saving and loading
Expand Down Expand Up @@ -429,6 +441,7 @@ class GD_CORE_API Layout {

EventsList events; ///< Scene events
gd::EditorSettings editorSettings;
double renderer3DWorldScale = 100;

/**
* Initialize from another layout. Used by copy-ctor and assign-op.
Expand Down
4 changes: 2 additions & 2 deletions Extensions/3D/AmbientLight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ namespace gdjs {
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {
if (parameterName === 'intensity') {
this.light.intensity = value;
this.light.intensity = value * Math.PI;
}
}
getDoubleParameter(parameterName: string): number {
if (parameterName === 'intensity') {
return this.light.intensity;
return this.light.intensity / Math.PI;
}
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions Extensions/3D/CustomRuntimeObject3DRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,14 @@ namespace gdjs {
getAnimationFrameWidth(material: THREE.Material) {
const map = (
material as THREE.MeshBasicMaterial | THREE.MeshStandardMaterial
).map;
).map as THREE.Texture<HTMLImageElement>;
return map ? map.image.width : 0;
}

getAnimationFrameHeight(material: THREE.Material) {
const map = (
material as THREE.MeshBasicMaterial | THREE.MeshStandardMaterial
).map;
).map as THREE.Texture<HTMLImageElement>;
return map ? map.image.height : 0;
}
}
Expand Down
33 changes: 21 additions & 12 deletions Extensions/3D/DirectionalLight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,22 @@ namespace gdjs {
this._light.shadow.camera.updateProjectionMatrix();
}

private _updateShadowCamera(): void {
private _updateShadowCamera(scene: gdjs.RuntimeScene): void {
if (!this._shadowCameraDirty) {
return;
}
this._shadowCameraDirty = false;

this._light.shadow.camera.near = 1;
this._light.shadow.camera.far = this._distanceFromCamera + 10000;
this._light.shadow.camera.right = this._frustumSize / 2;
this._light.shadow.camera.left = -this._frustumSize / 2;
this._light.shadow.camera.top = this._frustumSize / 2;
this._light.shadow.camera.bottom = -this._frustumSize / 2;
const inverseWorldScale = scene.getRenderer3DInverseWorldScale();
const frustumSize = this._frustumSize * inverseWorldScale;

this._light.shadow.camera.near = 1 * inverseWorldScale;
this._light.shadow.camera.far =
(this._distanceFromCamera + 10000) * inverseWorldScale;
this._light.shadow.camera.right = frustumSize / 2;
this._light.shadow.camera.left = -frustumSize / 2;
this._light.shadow.camera.top = frustumSize / 2;
this._light.shadow.camera.bottom = -frustumSize / 2;
}

private _updateShadowMapSize(): void {
Expand Down Expand Up @@ -124,8 +128,11 @@ namespace gdjs {
return true;
}
updatePreRender(target: gdjs.EffectsTarget): any {
const scene = target.getRuntimeScene().getScene();
const inverseWorldScale = scene.getRenderer3DInverseWorldScale();

// Apply any update to the camera or shadow map size.
this._updateShadowCamera();
this._updateShadowCamera(scene);
this._updateShadowMapSize();

// Avoid shadow acne due to depth buffer precision.
Expand All @@ -135,7 +142,8 @@ namespace gdjs {
: this._shadowMapSize < 2048
? 1.25
: 1;
this._light.shadow.bias = -this._minimumShadowBias * biasMultiplier;
this._light.shadow.bias =
-this._minimumShadowBias * biasMultiplier * inverseWorldScale;

// Apply update to the light position and its target.
// By doing this, the shadows are "following" the GDevelop camera.
Expand All @@ -147,6 +155,8 @@ namespace gdjs {
const y = layer.getCameraY();
const z = layer.getCameraZ(layer.getInitialCamera3DFieldOfView());

// Contrary to cameras, lights are within the scene so they already
// take world scale into account.
const roundedX = Math.floor(x / 100) * 100;
const roundedY = Math.floor(y / 100) * 100;
const roundedZ = Math.floor(z / 100) * 100;
Expand Down Expand Up @@ -182,14 +192,13 @@ namespace gdjs {
roundedZ +
this._distanceFromCamera *
Math.sin(gdjs.toRad(this._elevation));

this._light.position.set(posLightX, posLightY, posLightZ);
this._light.target.position.set(roundedX, roundedY, roundedZ);
}
}
updateDoubleParameter(parameterName: string, value: number): void {
if (parameterName === 'intensity') {
this._light.intensity = value;
this._light.intensity = value * Math.PI;
} else if (parameterName === 'elevation') {
this._elevation = value;
} else if (parameterName === 'rotation') {
Expand All @@ -204,7 +213,7 @@ namespace gdjs {
}
getDoubleParameter(parameterName: string): number {
if (parameterName === 'intensity') {
return this._light.intensity;
return this._light.intensity / Math.PI;
} else if (parameterName === 'elevation') {
return this._elevation;
} else if (parameterName === 'rotation') {
Expand Down
8 changes: 6 additions & 2 deletions Extensions/3D/ExponentialFog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,17 @@ namespace gdjs {
}
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {
const scene = target.getRuntimeScene().getScene();
const worldScale = scene.getRenderer3DWorldScale();
if (parameterName === 'density') {
this.fog.density = value;
this.fog.density = value * worldScale;
}
}
getDoubleParameter(parameterName: string): number {
const scene = target.getRuntimeScene().getScene();
const inverseWorldScale = scene.getRenderer3DInverseWorldScale();
if (parameterName === 'density') {
return this.fog.density;
return this.fog.density * inverseWorldScale;
}
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions Extensions/3D/HemisphereLight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ namespace gdjs {
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {
if (parameterName === 'intensity') {
this._light.intensity = value;
this._light.intensity = value * Math.PI;
} else if (parameterName === 'elevation') {
this._elevation = value;
this.updateRotation();
Expand All @@ -81,7 +81,7 @@ namespace gdjs {
}
getDoubleParameter(parameterName: string): number {
if (parameterName === 'intensity') {
return this._light.intensity;
return this._light.intensity / Math.PI;
} else if (parameterName === 'elevation') {
return this._elevation;
} else if (parameterName === 'rotation') {
Expand Down
12 changes: 8 additions & 4 deletions Extensions/3D/LinearFog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,21 @@ namespace gdjs {
}
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {
const scene = target.getRuntimeScene().getScene();
const inverseWorldScale = scene.getRenderer3DInverseWorldScale();
if (parameterName === 'near') {
this.fog.near = value;
this.fog.near = value * inverseWorldScale;
} else if (parameterName === 'far') {
this.fog.far = value;
this.fog.far = value * inverseWorldScale;
}
}
getDoubleParameter(parameterName: string): number {
const scene = target.getRuntimeScene().getScene();
const worldScale = scene.getRenderer3DWorldScale();
if (parameterName === 'near') {
return this.fog.near;
return this.fog.near * worldScale;
} else if (parameterName === 'far') {
return this.fog.far;
return this.fog.far * worldScale;
}
return 0;
}
Expand Down
14 changes: 10 additions & 4 deletions Extensions/3D/Scene3DTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,12 @@ namespace gdjs {
} else {
threeCamera.up.set(0, 0, 1);
}
const inverseWorldScale = runtimeScene.getRenderer3DInverseWorldScale();
threeCamera.lookAt(
object.getCenterXInScene(),
-object.getCenterYInScene(),
object.getCenterXInScene() * inverseWorldScale,
-object.getCenterYInScene() * inverseWorldScale,
//@ts-ignore
object.getZ ? object.getZ() : 0
object.getZ ? object.getZ() * inverseWorldScale : 0
);
// The layer angle takes over the 3D camera Z rotation.
layer.setCameraRotation(gdjs.toDegrees(-threeCamera.rotation.z));
Expand All @@ -208,7 +209,12 @@ namespace gdjs {
} else {
threeCamera.up.set(0, 0, 1);
}
threeCamera.lookAt(x, -y, z);
const inverseWorldScale = runtimeScene.getRenderer3DInverseWorldScale();
threeCamera.lookAt(
x * inverseWorldScale,
-y * inverseWorldScale,
z * inverseWorldScale
);
// The layer angle takes over the 3D camera Z rotation.
layer.setCameraRotation(gdjs.toDegrees(-threeCamera.rotation.z));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
1 change: 1 addition & 0 deletions Extensions/LinkedObjects/tests/linkedobjects.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('gdjs.LinksManager', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
usedResources: [],
uiSettings: {
grid: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('gdjs.ShapePainterRuntimeObject (using a PixiJS RuntimeGame with assets
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
1 change: 1 addition & 0 deletions Extensions/SaveState/tests/SaveState.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe('SaveState', () => {
name: name,
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: objects || [
// @ts-ignore - This is a gdjs.SpriteObjectData.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ describe('gdjs.TileMapCollisionMaskRuntimeObject', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('gdjs.TopDownMovementRuntimeBehavior', function () {
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
renderer3DWorldScale: 100,
behaviorsSharedData: [],
objects: [],
objectsGroups: [],
Expand Down
Loading
Loading