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>
@@ -49,7 +49,7 @@ def copy_assets():
|
|||||||
It preserves the relative directory structure per sample so that each sample's
|
It preserves the relative directory structure per sample so that each sample's
|
||||||
assets are isolated.
|
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 root, dirs, files in os.walk(OUT_DIR):
|
||||||
for f in files:
|
for f in files:
|
||||||
if any(f.endswith(ext) for ext in exts):
|
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
|
files (which assume assets are alongside them) need to be patched to point to the correct
|
||||||
relative paths based on their nesting depth.
|
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'
|
asset_pattern = r'([\'"`])((?:\.\.\/)?(?:[\w\-\/]+\.)(?:' + exts + r'))\1'
|
||||||
|
|
||||||
for f in files_to_fix:
|
for f in files_to_fix:
|
||||||
@@ -95,6 +95,8 @@ def fix_paths():
|
|||||||
def asset_repl(m):
|
def asset_repl(m):
|
||||||
quote = m.group(1)
|
quote = m.group(1)
|
||||||
path = m.group(2)
|
path = m.group(2)
|
||||||
|
if "lib/" in path:
|
||||||
|
return m.group(0)
|
||||||
if path.startswith("../"):
|
if path.startswith("../"):
|
||||||
return f"{quote}{depth_prefix}assets/{path[3:]}{quote}"
|
return f"{quote}{depth_prefix}assets/{path[3:]}{quote}"
|
||||||
else:
|
else:
|
||||||
@@ -116,6 +118,8 @@ def fix_paths():
|
|||||||
|
|
||||||
text = re.sub(r'(\w+(?:\.\w+)*)\.loadResources\(([^)]*)\);', fix_load_resources, text)
|
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:
|
with open(f, 'w') as file:
|
||||||
file.write(text)
|
file.write(text)
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,15 @@
|
|||||||
"out/cmake-webgl-release/web/examples/examples/skinning/skinning.html": {
|
"out/cmake-webgl-release/web/examples/examples/skinning/skinning.html": {
|
||||||
"dest": "samples/web/skinning.md"
|
"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": {
|
"out/cmake-webgl-release/web/examples/examples/remote/remote.html": {
|
||||||
"dest": "remote/index.html"
|
"dest": "remote/index.html"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ def pull_duplicates():
|
|||||||
if body_match:
|
if body_match:
|
||||||
content = style_str + body_match.group(1)
|
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:
|
with open(new_fpath, 'w') as out_file:
|
||||||
for line in content.splitlines(True):
|
for line in content.splitlines(True):
|
||||||
out_file.write(transform_dup_file_link(line, link_transforms))
|
out_file.write(transform_dup_file_link(line, link_transforms))
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ def snapshot_samples():
|
|||||||
|
|
||||||
driver = webdriver.Chrome(options=chrome_options)
|
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:
|
for sample in samples:
|
||||||
print(f"Taking snapshot of {sample}...")
|
print(f"Taking snapshot of {sample}...")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
- [morphing](./samples/web/morphing.md)
|
- [morphing](./samples/web/morphing.md)
|
||||||
- [parquet](./samples/web/parquet.md)
|
- [parquet](./samples/web/parquet.md)
|
||||||
- [skinning](./samples/web/skinning.md)
|
- [skinning](./samples/web/skinning.md)
|
||||||
|
- [sky](./samples/web/sky.md)
|
||||||
- [Technical Notes](./notes/README.md)
|
- [Technical Notes](./notes/README.md)
|
||||||
- [Material Properties](./notes/material_properties.md)
|
- [Material Properties](./notes/material_properties.md)
|
||||||
- [Release](./release/README.md)
|
- [Release](./release/README.md)
|
||||||
|
|||||||
BIN
docs_src/src_mdbook/src/images/web_sample_sky.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@@ -62,4 +62,8 @@ Here are some additional standalone examples demonstrating Filament's capabiliti
|
|||||||
<img src="../../images/web_sample_skinning.png" alt="skinning" />
|
<img src="../../images/web_sample_skinning.png" alt="skinning" />
|
||||||
<span>skinning</span>
|
<span>skinning</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="sky.md" class="sample-card">
|
||||||
|
<img src="../../images/web_sample_sky.png" alt="sky" />
|
||||||
|
<span>sky</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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`
|
|
||||||
28
docs_src/src_raw/wip/sky/gl-matrix-min.js
vendored
@@ -1,9 +0,0 @@
|
|||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
canvas {
|
|
||||||
touch-action: none;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
@@ -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.
|
- Automatically detects the built files in the `out/` directory.
|
||||||
- Generates a main entry `index.html` listing all the available samples and tutorials.
|
- 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.
|
- 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.
|
||||||
|
|||||||
@@ -194,4 +194,15 @@ add_envmap("third_party/environments/lightroom_14b.hdr" "default_env" ${TARGET_D
|
|||||||
set(TARGET_DIR "remote")
|
set(TARGET_DIR "remote")
|
||||||
add_localfile("remote.html" "remote.html" ${TARGET_DIR} ALL_DEMO_ASSETS)
|
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})
|
add_custom_target(${PROJECT_NAME} ALL DEPENDS ${ALL_DEMO_ASSETS})
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<title>Analytic Skybox</title>
|
<title>Analytic Skybox</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
|
<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>
|
<style>
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -23,22 +23,24 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<canvas></canvas>
|
<div style="display:flex;flex-direction:column;align-items:center">
|
||||||
|
<canvas></canvas>
|
||||||
|
<!-- mdbook: add fullscreen mode -->
|
||||||
|
</div>
|
||||||
<!-- Filament -->
|
<!-- Filament -->
|
||||||
<script src="filament.js"></script>
|
<script src="../filament.js"></script>
|
||||||
<script src="gl-matrix-min.js"></script>
|
<script src="../gl-matrix-min.js"></script>
|
||||||
|
|
||||||
<!-- UI -->
|
<!-- UI -->
|
||||||
<script src="lil-gui.js"></script>
|
<script src="lil-gui.js"></script>
|
||||||
|
|
||||||
<!-- Utils -->
|
<!-- Utils -->
|
||||||
<script src="assets/suncalc_global.js"></script>
|
<script src="suncalc_global.js"></script>
|
||||||
|
|
||||||
<!-- App -->
|
<!-- App -->
|
||||||
|
<script>window.FILAMENT_ASSET_DIR = "";</script>
|
||||||
<script src="SimulatedSkybox.js?v=9999"></script>
|
<script src="SimulatedSkybox.js"></script>
|
||||||
<script src="main.js?v=9999"></script>
|
<script src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -66,7 +66,7 @@ class SimulatedSkybox {
|
|||||||
|
|
||||||
// Load Moon Texture
|
// Load Moon Texture
|
||||||
try {
|
try {
|
||||||
const texUrl = 'assets/moon_disk.png';
|
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'moon_disk.png';
|
||||||
const Texture = Filament.Texture;
|
const Texture = Filament.Texture;
|
||||||
const TextureSampler = Filament.TextureSampler;
|
const TextureSampler = Filament.TextureSampler;
|
||||||
const PixelDataFormat = Filament.PixelDataFormat;
|
const PixelDataFormat = Filament.PixelDataFormat;
|
||||||
@@ -125,7 +125,7 @@ class SimulatedSkybox {
|
|||||||
|
|
||||||
// Load Moon Normal
|
// Load Moon Normal
|
||||||
try {
|
try {
|
||||||
const texUrl = 'assets/moon_normal.png';
|
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'moon_normal.png';
|
||||||
const Texture = Filament.Texture;
|
const Texture = Filament.Texture;
|
||||||
const TextureSampler = Filament.TextureSampler;
|
const TextureSampler = Filament.TextureSampler;
|
||||||
const PixelDataFormat = Filament.PixelDataFormat;
|
const PixelDataFormat = Filament.PixelDataFormat;
|
||||||
@@ -182,7 +182,7 @@ class SimulatedSkybox {
|
|||||||
|
|
||||||
// Load Milky Way Texture
|
// Load Milky Way Texture
|
||||||
try {
|
try {
|
||||||
const texUrl = 'assets/milkyway.png';
|
const texUrl = (window.FILAMENT_ASSET_DIR || '') + 'milkyway.png';
|
||||||
const Texture = Filament.Texture;
|
const Texture = Filament.Texture;
|
||||||
const TextureSampler = Filament.TextureSampler;
|
const TextureSampler = Filament.TextureSampler;
|
||||||
const PixelDataFormat = Filament.PixelDataFormat;
|
const PixelDataFormat = Filament.PixelDataFormat;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
// main.js
|
// 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]);
|
window.app = new App(document.getElementsByTagName('canvas')[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ class App {
|
|||||||
|
|
||||||
// Load the material explicitly. SimulatedSkybox.loadMaterial fetches it.
|
// 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.skybox.loadMaterial(matUrl).then(() => {
|
||||||
this.initGUI();
|
this.initGUI();
|
||||||
});
|
});
|
||||||
@@ -3,8 +3,8 @@ set -e
|
|||||||
|
|
||||||
# Default size
|
# Default size
|
||||||
SIZE=${1:-256}
|
SIZE=${1:-256}
|
||||||
OUTPUT_COLOR="../assets/moon_disk.png"
|
OUTPUT_COLOR="../../textures/sky/moon_disk.png"
|
||||||
OUTPUT_NORMAL="../assets/moon_normal.png"
|
OUTPUT_NORMAL="../../textures/sky/moon_normal.png"
|
||||||
|
|
||||||
# Navigate to script directory
|
# Navigate to script directory
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
Before Width: | Height: | Size: 447 KiB After Width: | Height: | Size: 447 KiB |
|
Before Width: | Height: | Size: 596 KiB After Width: | Height: | Size: 596 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |