A new Sky simulation Web demo (#9828)

* sky simulation sample

Also added documentation on how to add another web sample

---------

Co-authored-by: Powei Feng <powei@google.com>
This commit is contained in:
Mathias Agopian
2026-03-26 22:40:34 -07:00
committed by GitHub
parent 566aeac5ed
commit 4b040fbae6
31 changed files with 89 additions and 1507 deletions

View File

@@ -49,7 +49,7 @@ def copy_assets():
It preserves the relative directory structure per sample so that each sample's
assets are isolated.
"""
exts = ['.filamat', '.filamesh', '.ktx', '.ktx2', '.png', '.jpg', '.bin', '.glb', '.gltf', '.hdr', '.css']
exts = ['.filamat', '.filamesh', '.ktx', '.ktx2', '.png', '.jpg', '.bin', '.glb', '.gltf', '.hdr', '.css', '.js']
for root, dirs, files in os.walk(OUT_DIR):
for f in files:
if any(f.endswith(ext) for ext in exts):
@@ -66,9 +66,9 @@ def fix_paths():
files (which assume assets are alongside them) need to be patched to point to the correct
relative paths based on their nesting depth.
"""
files_to_fix = glob.glob(f"{BOOK_DIR}/samples/web/*.html") + glob.glob(f"{BOOK_DIR}/remote/*.html")
files_to_fix = glob.glob(f"{BOOK_DIR}/samples/web/*.html") + glob.glob(f"{BOOK_DIR}/remote/*.html") + glob.glob(f"{BOOK_DIR}/web/*.html")
exts = "filamat|filamesh|ktx|ktx2|png|jpg|bin|glb|gltf|hdr|css"
exts = "filamat|filamesh|ktx|ktx2|png|jpg|bin|glb|gltf|hdr|css|js"
asset_pattern = r'([\'"`])((?:\.\.\/)?(?:[\w\-\/]+\.)(?:' + exts + r'))\1'
for f in files_to_fix:
@@ -95,6 +95,8 @@ def fix_paths():
def asset_repl(m):
quote = m.group(1)
path = m.group(2)
if "lib/" in path:
return m.group(0)
if path.startswith("../"):
return f"{quote}{depth_prefix}assets/{path[3:]}{quote}"
else:
@@ -116,6 +118,8 @@ def fix_paths():
text = re.sub(r'(\w+(?:\.\w+)*)\.loadResources\(([^)]*)\);', fix_load_resources, text)
text = text.replace('window.FILAMENT_ASSET_DIR = "";', f'window.FILAMENT_ASSET_DIR = "{depth_prefix}assets/{sample_name}/";')
with open(f, 'w') as file:
file.write(text)

View File

@@ -130,6 +130,15 @@
"out/cmake-webgl-release/web/examples/examples/skinning/skinning.html": {
"dest": "samples/web/skinning.md"
},
"out/cmake-webgl-release/web/examples/examples/sky/sky.html": {
"dest": "samples/web/sky.md",
"replacements": {
"<!-- mdbook: add fullscreen mode -->": "<a href=\"../../web/sky.html\">Full screen</a>"
}
},
"./out/cmake-webgl-release/web/examples/examples/sky/sky.html": {
"dest": "web/sky.html"
},
"out/cmake-webgl-release/web/examples/examples/remote/remote.html": {
"dest": "remote/index.html"
}

View File

@@ -88,6 +88,10 @@ def pull_duplicates():
if body_match:
content = style_str + body_match.group(1)
replacements = config[fin].get('replacements', {})
for old, new in replacements.items():
content = content.replace(old, new)
with open(new_fpath, 'w') as out_file:
for line in content.splitlines(True):
out_file.write(transform_dup_file_link(line, link_transforms))

View File

@@ -71,7 +71,7 @@ def snapshot_samples():
driver = webdriver.Chrome(options=chrome_options)
samples = ['animation', 'cube_fl0', 'helmet', 'morphing', 'parquet', 'skinning', 'triangle', 'redball', 'suzanne']
samples = ['animation', 'cube_fl0', 'helmet', 'morphing', 'parquet', 'skinning', 'sky', 'triangle', 'redball', 'suzanne']
for sample in samples:
print(f"Taking snapshot of {sample}...")

View File

@@ -21,6 +21,7 @@
- [morphing](./samples/web/morphing.md)
- [parquet](./samples/web/parquet.md)
- [skinning](./samples/web/skinning.md)
- [sky](./samples/web/sky.md)
- [Technical Notes](./notes/README.md)
- [Material Properties](./notes/material_properties.md)
- [Release](./release/README.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -62,4 +62,8 @@ Here are some additional standalone examples demonstrating Filament's capabiliti
<img src="../../images/web_sample_skinning.png" alt="skinning" />
<span>skinning</span>
</a>
<a href="sky.md" class="sample-card">
<img src="../../images/web_sample_sky.png" alt="sky" />
<span>sky</span>
</a>
</div>

View File

@@ -1,40 +0,0 @@
# Building Skybox Assets
This directory contains the source code for the Simulated Skybox sample. The assets (material and textures) are pre-built in the `assets/` directory.
If you need to modify the material or regenerate the moon textures, you can use the scripts provided in the `tools/` directory.
## Prerequisites
- **Filament**: You must have a built version of Filament. The scripts assume a standard CMake build output structure (e.g., `out/cmake-release`).
- **Python 3**: Required for texture generation.
- **Python Dependencies**: `numpy`, `Pillow` (automatically installed if missing, via pip).
## Rebuilding the Material
If you modify `simulated_skybox.mat`, you must recompile it into a `.filamat` file.
```bash
# Run from the sample root or tools directory
./tools/build_material.sh
```
This will update `assets/simulated_skybox.filamat`.
## Regenerating Moon Textures
If you want to change the moon's resolution, bump scale, or blur, you can regenerate the textures.
```bash
# Run from the sample root or tools directory
./tools/generate_moon_assets.sh [size]
```
Example:
```bash
./tools/generate_moon_assets.sh 512
```
This will download raw NASA data (if not present) and generate:
- `assets/moon_disk.png`
- `assets/moon_normal.png`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +0,0 @@
body {
margin: 0;
overflow: hidden;
}
canvas {
touch-action: none;
width: 100%;
height: 100%;
}

View File

@@ -61,3 +61,36 @@ The custom `serve.py` script in the `web/examples/` directory performs the follo
- Automatically detects the built files in the `out/` directory.
- Generates a main entry `index.html` listing all the available samples and tutorials.
- Handles server-side rendering of `.md` tutorial files into HTML using an embedded template.
## Porting a Web Sample to Official Docs (`docs_src`)
If you want your web sample or tutorial to appear on the official Filament documentation website via
`mdbook`, follow these steps:
1. **Map the Built HTML:**
Add your generated `.html` or `.md` file to the mapping in `docs_src/build/duplicates.json`. This
tells the documentation build script to copy your sample into the `mdbook` structure.
```json
"out/cmake-webgl-release/web/examples/examples/your_sample/your_sample.html": {
"dest": "samples/web/your_sample.md"
}
```
2. **Add to the Navigation Menu:**
Link your sample in the table of contents by adding it to `docs_src/src_mdbook/src/SUMMARY.md`
under the "Web Tutorials" or "Web Samples" section.
3. **Generate a Thumbnail Image:**
Add your sample's name to the `samples` array in `docs_src/build/snapshot_samples.py`. Then,
manually run this script (`python3 snapshot_samples.py`). It will launch a headless browser,
wait for your scene to render, and snap a 100x100 preview image.
4. **Dynamic Asset Loading (Optional):**
When `mdbook` serves your sample, the assets (`.filamat`, textures) are segregated into a
`web/assets/` directory.
- For `<script src="...">` or `<img src="...">` tags embedded in the HTML, the paths will be
automatically rewritten by `docs_src/build/copy_web_docs.py`.
- However, if you load files dynamically within your JavaScript code (e.g., using `fetch()`), you
**must** prepend `(window.FILAMENT_ASSET_DIR || '')` to the file URL.
- If you need `window.FILAMENT_ASSET_DIR` to be properly populated, make sure to add logic to
`docs_src/build/copy_web_docs.py` to inject the proper path prefix for your sample.

View File

@@ -194,4 +194,15 @@ add_envmap("third_party/environments/lightroom_14b.hdr" "default_env" ${TARGET_D
set(TARGET_DIR "remote")
add_localfile("remote.html" "remote.html" ${TARGET_DIR} ALL_DEMO_ASSETS)
set(TARGET_DIR "sky")
add_localfile("sky.html" "sky.html" ${TARGET_DIR} ALL_DEMO_ASSETS)
build_material("materials/simulated_skybox.mat" ${TARGET_DIR} "simulated_skybox" ALL_DEMO_ASSETS)
add_localfile("sky/lil-gui.js" "lil-gui.js" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("sky/suncalc_global.js" "suncalc_global.js" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("sky/main.js" "main.js" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("sky/SimulatedSkybox.js" "SimulatedSkybox.js" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("textures/sky/moon_disk.png" "moon_disk.png" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("textures/sky/moon_normal.png" "moon_normal.png" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_localfile("textures/sky/milkyway.png" "milkyway.png" ${TARGET_DIR} ALL_DEMO_ASSETS)
add_custom_target(${PROJECT_NAME} ALL DEPENDS ${ALL_DEMO_ASSETS})

View File

@@ -5,7 +5,7 @@
<title>Analytic Skybox</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<link href="styles.css" rel="stylesheet">
<link href="../main.css" rel="stylesheet">
<style>
body {
margin: 0;
@@ -23,22 +23,24 @@
</head>
<body>
<canvas></canvas>
<div style="display:flex;flex-direction:column;align-items:center">
<canvas></canvas>
<!-- mdbook: add fullscreen mode -->
</div>
<!-- Filament -->
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script src="../filament.js"></script>
<script src="../gl-matrix-min.js"></script>
<!-- UI -->
<script src="lil-gui.js"></script>
<!-- Utils -->
<script src="assets/suncalc_global.js"></script>
<script src="suncalc_global.js"></script>
<!-- App -->
<script src="SimulatedSkybox.js?v=9999"></script>
<script src="main.js?v=9999"></script>
<script>window.FILAMENT_ASSET_DIR = "";</script>
<script src="SimulatedSkybox.js"></script>
<script src="main.js"></script>
</body>
</html>
</html>

View File

@@ -66,7 +66,7 @@ class SimulatedSkybox {
// Load Moon Texture
try {
const texUrl = 'assets/moon_disk.png';
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'moon_disk.png';
const Texture = Filament.Texture;
const TextureSampler = Filament.TextureSampler;
const PixelDataFormat = Filament.PixelDataFormat;
@@ -125,7 +125,7 @@ class SimulatedSkybox {
// Load Moon Normal
try {
const texUrl = 'assets/moon_normal.png';
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'moon_normal.png';
const Texture = Filament.Texture;
const TextureSampler = Filament.TextureSampler;
const PixelDataFormat = Filament.PixelDataFormat;
@@ -182,7 +182,7 @@ class SimulatedSkybox {
// Load Milky Way Texture
try {
const texUrl = 'assets/milkyway.png';
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'milkyway.png';
const Texture = Filament.Texture;
const TextureSampler = Filament.TextureSampler;
const PixelDataFormat = Filament.PixelDataFormat;

View File

@@ -1,7 +1,7 @@
// main.js
Filament.init(['assets/simulated_skybox.filamat?v=' + Date.now()], () => {
Filament.init([(window.FILAMENT_ASSET_DIR || '') + 'simulated_skybox.filamat?v=' + Date.now()], () => {
window.app = new App(document.getElementsByTagName('canvas')[0]);
});
@@ -130,7 +130,7 @@ class App {
// Load the material explicitly. SimulatedSkybox.loadMaterial fetches it.
const matUrl = 'assets/simulated_skybox.filamat?v=' + Date.now();
const matUrl = (window.FILAMENT_ASSET_DIR || '') + 'simulated_skybox.filamat?v=' + Date.now();
this.skybox.loadMaterial(matUrl).then(() => {
this.initGUI();
});

View File

@@ -3,8 +3,8 @@ set -e
# Default size
SIZE=${1:-256}
OUTPUT_COLOR="../assets/moon_disk.png"
OUTPUT_NORMAL="../assets/moon_normal.png"
OUTPUT_COLOR="../../textures/sky/moon_disk.png"
OUTPUT_NORMAL="../../textures/sky/moon_normal.png"
# Navigate to script directory
cd "$(dirname "$0")"

View File

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 447 KiB

View File

Before

Width:  |  Height:  |  Size: 596 KiB

After

Width:  |  Height:  |  Size: 596 KiB

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB