Skip to content
Open
Changes from all commits
Commits
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
312 changes: 312 additions & 0 deletions extensions/community/CinematicSky.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
{
"author": "",
"category": "Visual Effect",
"dimension": "3D",
"extensionNamespace": "",
"fullName": "Cinematic Sky",
"gdevelopVersion": "",
"helpPath": "",
"iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXdoaXRlLWJhbGFuY2Utc3VubnkiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMy41NSwxOC41NEw0Ljk2LDE5Ljk1TDYuNzYsMTguMTZMNS4zNCwxNi43NE0xMSwyMi40NUMxMS4zMiwyMi40NSAxMywyMi40NSAxMywyMi40NVYxOS41SDExTTEyLDUuNUE2LDYgMCAwLDAgNiwxMS41QTYsNiAwIDAsMCAxMiwxNy41QTYsNiAwIDAsMCAxOCwxMS41QzE4LDguMTggMTUuMzEsNS41IDEyLDUuNU0yMCwxMi41SDIzVjEwLjVIMjBNMTcuMjQsMTguMTZMMTkuMDQsMTkuOTVMMjAuNDUsMTguNTRMMTguNjYsMTYuNzRNMjAuNDUsNC40NkwxOS4wNCwzLjA1TDE3LjI0LDQuODRMMTguNjYsNi4yNk0xMywwLjU1SDExVjMuNUgxM000LDEwLjVIMVYxMi41SDRNNi43Niw0Ljg0TDQuOTYsMy4wNUwzLjU1LDQuNDZMNS4zNCw2LjI2TDYuNzYsNC44NFoiIC8+PC9zdmc+",
"name": "CinematicSky",
"previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/9a2997986e89ee7f6d0b59c84f13a70c246fd201958496d48f63ab758ff9848e_white-balance-sunny.svg",
"shortDescription": "Adds a cinematic PBR sky with volumetric clouds.",
"version": "1.0.0",
"description": "An extension for creating a realistic sky (Unreal Engine-style) with dynamic clouds.",
"tags": [
"sky",
"3d",
"pbr",
"clouds"
],
"authorIds": [
"eDINELUbuNcjEaC9yA128lGrjmF2"
],
"dependencies": [],
"globalVariables": [],
"sceneVariables": [],
"eventsFunctions": [
{
"description": "Sets up the sky, configures lighting, and shadows.",
"fullName": "Set cinematic sky",
"functionType": "Action",
"name": "SetupCinematicSky",
"sentence": "Set sky (Sun X: _PARAM1_, Y: _PARAM2_, Z: _PARAM3_, Cloud Speed: _PARAM4_)",
"events": [
{
"type": "BuiltinCommonInstructions::JsCode",
"inlineCode": [
"// Get scene parameters",
"const sunX = eventsFunctionContext.getArgument(\"SunX\") || 400.0;",
"const sunY = eventsFunctionContext.getArgument(\"SunY\") || 200.0;",
"const sunZ = eventsFunctionContext.getArgument(\"SunZ\") || 150.0;",
"const cloudSpeed = eventsFunctionContext.getArgument(\"CloudSpeed\") || 1.0;",
"",
"// Access Three.js components",
"const layer = runtimeScene.getLayer(\"\");",
"const renderer = layer.getRenderer();",
"const threeScene = renderer.getThreeScene ? renderer.getThreeScene() : null;",
"const threeRenderer = renderer.getThreeRenderer ? renderer.getThreeRenderer() : null;",
"const camera = renderer.getThreeCamera ? renderer.getThreeCamera() : null;",
"",
"// Exit if Three.js not available",
"if (!threeScene || typeof THREE === \"undefined\") return;",
"",
"// Initialize sky if not already present",
"if (!threeScene.userData.customSkyInstalled) {",
" threeScene.userData.cloudSpeed = cloudSpeed;",
" const sunPos = new THREE.Vector3(sunX, sunY, sunZ);",
"",
" // --- Renderer Configuration ---",
" if (threeRenderer) {",
" ",
" // if (threeRenderer.useLegacyLights !== undefined) threeRenderer.useLegacyLights = false;",
" // if (threeRenderer.physicallyCorrectLights !== undefined) threeRenderer.physicallyCorrectLights = true;",
" // threeRenderer.outputColorSpace = THREE.SRGBColorSpace || 3001;",
" // if (threeRenderer.outputEncoding) threeRenderer.outputEncoding = 3001;",
" // threeRenderer.toneMapping = THREE.ACESFilmicToneMapping;",
" // threeRenderer.toneMappingExposure = 1.15;",
"",
" threeRenderer.shadowMap.enabled = true;",
" threeRenderer.shadowMap.type = THREE.PCFSoftShadowMap;",
" }",
"",
" // Set camera far plane",
" if (camera) camera.far = 50000;",
"",
" // --- Lighting Setup ---",
" // Atmospheric fog",
" threeScene.fog = new THREE.FogExp2(0x7aa5e8, 0.00015);",
"",
" // Ambient light from hemisphere",
" const hemiLight = new THREE.HemisphereLight(0xbbeeff, 0x222233, 0.6);",
" threeScene.add(hemiLight);",
"",
" // Main directional light (sun)",
" const sunLight = new THREE.DirectionalLight(0xfff5e6, 1.5); ",
" sunLight.position.copy(sunPos);",
" sunLight.castShadow = true;",
"",
" // High-res shadows",
" sunLight.shadow.mapSize.width = 4096;",
" sunLight.shadow.mapSize.height = 4096;",
" sunLight.shadow.camera.near = 10;",
" sunLight.shadow.camera.far = 4000;",
" sunLight.shadow.bias = -0.0002;",
" // Shadow camera frustum",
" const d = 1000;",
" sunLight.shadow.camera.left = -d;",
" sunLight.shadow.camera.right = d;",
" sunLight.shadow.camera.top = d;",
" sunLight.shadow.camera.bottom = -d;",
" threeScene.add(sunLight);",
"",
" // Fill light for softer shadows",
" const fillLight = new THREE.DirectionalLight(0x5577aa, 1.0);",
" fillLight.position.set(-sunPos.x, -sunPos.y, 100.0);",
" threeScene.add(fillLight);",
"",
" // --- Sky Shader ---",
" const vShader = `",
" varying vec3 vWorldPosition;",
" void main() {",
" vec4 worldPosition = modelMatrix * vec4(position, 1.0);",
" vWorldPosition = worldPosition.xyz;",
" gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
" }",
" `;",
"",
" const fShader = `",
" uniform float time;",
" uniform vec3 sunPosition;",
" varying vec3 vWorldPosition;",
"",
" // Noise functions for clouds",
" float hash(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); }",
" float noise(vec2 p) {",
" vec2 i = floor(p), f = fract(p);",
" vec2 u = f*f*(3.0-2.0*f);",
" return mix(mix(hash(i + vec2(0.0,0.0)), hash(i + vec2(1.0,0.0)), u.x),",
" mix(hash(i + vec2(0.0,1.0)), hash(i + vec2(1.0,1.0)), u.x), u.y);",
" }",
" float fbm(vec2 p) {",
" float f = 0.0, a = 0.5;",
" for(int i=0; i<7; i++) { f += a*noise(p); p*=2.01; a*=0.5; }",
" return f;",
" }",
"",
" void main() {",
" vec3 dir = normalize(vWorldPosition);",
" vec3 sunDir = normalize(sunPosition);",
" float height = max(dir.z, 0.0);",
"",
" // Sky gradient from horizon to zenith",
" vec3 zenithColor = vec3(0.03, 0.12, 0.40);",
" vec3 horizonColor = vec3(0.55, 0.70, 0.95);",
" vec3 skyColor = mix(horizonColor, zenithColor, pow(height, 0.6));",
"",
" // Sun glow effects",
" float sunDot = clamp(dot(dir, sunDir), 0.0, 1.0);",
" float sunCore = pow(sunDot, 40000.0) * 20.0;",
" float sunHalo = pow(sunDot, 500.0) * 1.5;",
" float sunAtmosphere = pow(sunDot, 20.0) * 0.4;",
" vec3 sunColor = vec3(1.0, 0.98, 0.95) * sunCore +",
" vec3(1.0, 0.85, 0.6) * sunHalo +",
" vec3(1.0, 0.7, 0.4) * sunAtmosphere;",
"",
" // Cloud generation",
" vec2 cloudUV = dir.xy / (height + 0.1) * 1.2;",
" vec2 warp = vec2(fbm(cloudUV + time * 0.01), fbm(cloudUV + vec2(5.2, 1.3) - time * 0.008));",
" float baseClouds = fbm(cloudUV + warp * 1.2 + time * 0.01);",
" float detailNoise = noise(cloudUV * 8.0 - time * 0.05) * 0.15;",
" float cloudNoise = baseClouds - detailNoise;",
" float cloudMask = smoothstep(0.4, 0.8, cloudNoise);",
" cloudMask *= smoothstep(0.0, 0.2, height); // Fade clouds near horizon",
"",
" // Cloud shading and light scattering",
" float cloudShade = fbm(cloudUV + warp * 1.5 + time * 0.01 + vec2(0.15));",
" vec3 cloudBaseColor = mix(vec3(0.25, 0.3, 0.4), vec3(1.0, 1.0, 1.0), smoothstep(0.2, 0.8, cloudShade));",
" float sss = pow(sunDot, 5.0) * (1.0 - cloudShade) * cloudMask * 2.0; // Subsurface scattering",
" vec3 sssColor = vec3(1.0, 0.75, 0.3) * sss;",
" float silverLining = pow(sunDot, 10.0) * 2.0;",
" vec3 cloudHighlight = vec3(1.0, 0.9, 0.7) * silverLining * (1.0 - cloudShade);",
" vec3 finalCloudColor = cloudBaseColor + cloudHighlight + sssColor;",
" float distanceFade = smoothstep(0.0, 0.4, height);",
" finalCloudColor = mix(horizonColor, finalCloudColor, distanceFade);",
"",
" // Combine sky, sun, and clouds",
" vec3 finalColor = skyColor + sunColor;",
" finalColor = mix(finalColor, finalCloudColor, cloudMask * 0.98);",
"",
" gl_FragColor = vec4(finalColor, 1.0);",
" }",
" `;",
"",
" const uniforms = {",
" time: { value: 0.0 },",
" sunPosition: { value: sunPos }",
" };",
"",
" // Create sky material and mesh",
" const skyMat = new THREE.ShaderMaterial({",
" vertexShader: vShader,",
" fragmentShader: fShader,",
" uniforms: uniforms,",
" side: THREE.BackSide,",
" depthWrite: false,",
" depthTest: false,",
" fog: false",
" });",
"",
" const skyGeo = new THREE.SphereGeometry(5000, 32, 32);",
" const skyMesh = new THREE.Mesh(skyGeo, skyMat);",
" ",
" skyMesh.renderOrder = -10000; ",
" skyMesh.frustumCulled = false; ",
"",
" threeScene.add(skyMesh);",
"",
"",
"",
" // --- IBL Generator (for reflections) ---",
" if (threeRenderer) {",
" const pmremGenerator = new THREE.PMREMGenerator(threeRenderer);",
" pmremGenerator.compileEquirectangularShader();",
" threeScene.userData.pmremGenerator = pmremGenerator;",
" }",
"",
" // Mark sky as installed and store references",
" threeScene.userData.customSkyInstalled = true;",
" threeScene.userData.skyMaterial = skyMat;",
" threeScene.userData.skyMesh = skyMesh;",
" threeScene.userData.envMapGenerated = false;",
"",
" // --- Automatic Update Loop ---",
" const updateSkyAuto = () => {",
" // Stop if scene reloaded or sky removed",
" if (!threeScene || !threeScene.userData.customSkyInstalled || !skyMesh.parent) {",
" return;",
" }",
"",
" const speed = threeScene.userData.cloudSpeed || 1.0;",
" // Boost speed for noticeable cloud movement at default '1'",
" const timeNow = (runtimeScene.getTimeManager().getTimeFromStart() / 1000.0) * speed * 1.0;",
"",
" // Update shader time uniform",
" skyMat.uniforms.time.value = timeNow;",
"",
" // Keep sky centered on camera",
" const activeCamera = renderer.getThreeCamera ? renderer.getThreeCamera() : camera;",
" if (activeCamera) {",
" skyMesh.position.copy(activeCamera.position);",
" }",
"",
"",
" // Generate environment map after a short delay",
" if (!threeScene.userData.envMapGenerated && threeScene.userData.pmremGenerator && timeNow > 0.5) {",
" const envScene = new THREE.Scene();",
" const tempSky = new THREE.Mesh(",
" new THREE.SphereGeometry(1000, 32, 32),",
" skyMat",
" );",
" envScene.add(tempSky);",
"",
" const renderTarget = threeScene.userData.pmremGenerator.fromScene(envScene);",
" threeScene.environment = renderTarget.texture;",
" threeScene.userData.pmremGenerator.dispose();",
" threeScene.userData.envMapGenerated = true;",
" }",
"",
" // Request next frame",
" requestAnimationFrame(updateSkyAuto);",
" };",
"",
" // Start the auto-update loop once",
" updateSkyAuto();",
"",
"} else {",
" // If sky already installed, just update parameters",
" threeScene.userData.cloudSpeed = cloudSpeed;",
"}",
""
],
"parameterObjects": "",
"useStrict": false,
"eventsSheetExpanded": true
}
],
"parameters": [
{
"description": "Sun X position (default 400)",
"name": "SunX",
"type": "expression"
},
{
"description": "Sun Y position (default 200)",
"name": "SunY",
"type": "expression"
},
{
"description": "Sun Z position (default 150)",
"name": "SunZ",
"type": "expression"
},
{
"description": "Cloud speed (default 1.0)",
"name": "CloudSpeed",
"type": "expression"
}
],
"objectGroups": []
}
],
"eventsFunctionsFolderStructure": {
"folderName": "__ROOT",
"children": [
{
"functionName": "SetupCinematicSky"
}
]
},
"eventsBasedBehaviors": [],
"eventsBasedObjects": []
}