Add tutorial that describes compression and async loading.

This commit is contained in:
Philip Rideout
2018-11-16 14:09:41 -08:00
parent b2a2da532a
commit ffff8437ba
9 changed files with 406 additions and 40 deletions
+9 -5
View File
@@ -4,15 +4,19 @@ date: 2018-10-30T13:13:14-07:00
menu: main
---
## documentation
## tutorials
- [JavaScript API reference](https://google.github.io/filament/webgl/reference.html)
- [Triangle Tutorial](https://google.github.io/filament/webgl/tutorial_triangle.html)
- [Redball Tutorial](https://google.github.io/filament/webgl/tutorial_redball.html)
- [WebGL Meetup Slides](https://prideout.net/slides/filawasm) (2018)
1. [Triangle Tutorial](https://google.github.io/filament/webgl/tutorial_triangle.html)
2. [Redball Tutorial](https://google.github.io/filament/webgl/tutorial_redball.html)
3. [Suzanne Tutorial](https://google.github.io/filament/webgl/tutorial_suzanne.html)
## demos
- [parquet](https://google.github.io/filament/webgl/parquet.html)
- [suzanne](https://google.github.io/filament/webgl/suzanne.html)
- [knotess](https://prideout.net/knotess/)
## other documentation
- [JavaScript API reference](https://google.github.io/filament/webgl/reference.html)
- [WebGL Meetup Slides](https://prideout.net/slides/filawasm) (2018)
+1 -1
View File
@@ -11,7 +11,7 @@ else()
set(CUSTOM_OUTPUTS)
set(CUSTOM_INPUTS)
foreach (NAME triangle redball)
foreach (NAME triangle redball suzanne)
list(APPEND CUSTOM_OUTPUTS ${PROJECT_BINARY_DIR}/demo_${NAME}.html)
list(APPEND CUSTOM_OUTPUTS ${PROJECT_BINARY_DIR}/tutorial_${NAME}.html)
list(APPEND CUSTOM_OUTPUTS ${PROJECT_BINARY_DIR}/tutorial_${NAME}.js)
+1 -1
View File
@@ -495,7 +495,7 @@ if __name__ == "__main__":
ENABLE_EMBEDDED_DEMO = not args.disable_demo
os.makedirs(os.path.realpath(OUTPUT_DIR), exist_ok=True)
for name in ["triangle", "redball"]:
for name in ["triangle", "redball", "suzanne"]:
weave(name)
tangle(name)
generate_demo_html(name)
+1
View File
@@ -14,6 +14,7 @@
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script src="https://unpkg.com/gltumble@1.0.0/gltumble.js"></script>
<script src="$SCRIPT"></script>
</body>
</html>
+25
View File
@@ -0,0 +1,25 @@
material {
name : textured,
requires : [ uv0 ],
shadingModel : lit,
parameters : [
{ type : sampler2d, name : albedo },
{ type : sampler2d, name : roughness },
{ type : sampler2d, name : metallic },
{ type : float, name : clearCoat },
{ type : sampler2d, name : normal },
{ type : sampler2d, name : ao }
],
}
fragment {
void material(inout MaterialInputs material) {
material.normal = texture(materialParams_normal, getUV0()).xyz * 2.0 - 1.0;
prepareMaterial(material);
material.baseColor = texture(materialParams_albedo, getUV0());
material.roughness = texture(materialParams_roughness, getUV0()).r;
material.metallic = texture(materialParams_metallic, getUV0()).r;
material.clearCoat = materialParams.clearCoat;
material.ambientOcclusion = texture(materialParams_ao, getUV0()).r;
}
}
+38 -27
View File
@@ -1,8 +1,11 @@
This tutorial will describe how to create the redball demo, introducing you to materials and
This tutorial will describe how to create the **redball** demo, introducing you to materials and
textures.
You'll need to use a couple command-line tools: `matc` and `cmgen`. You can find these in the
For starters, create a text file called `redball.html` and copy over the HTML that we used in the
[previous tutorial]. Change the last script tag from `triangle.js` to `redball.js`.
Next you'll need to get a couple command-line tools: `matc` and `cmgen`. You can find these in the
appropriate [Filament release](//github.com/google/filament/releases). You should choose the
archive that corresponds to your development machine rather than the one for web.
@@ -10,7 +13,7 @@ archive that corresponds to your development machine rather than the one for web
The `matc` tool consumes a text file containing a high-level description of a PBR material, and
produces a binary material package that contains shader code and associated metadata. For more
information, see the official document describing the [Filament Material System]().
information, see the official document describing the [Filament Material System].
Let's try out `matc`. Create the following file in your favorite text editor and call it
`plastic.mat`.
@@ -52,9 +55,6 @@ tutorial.
Next we'll use Filament's `cmgen` tool to consume a HDR environment map in latlong format, and
produce two cubemap files: a mipmapped IBL and a blurry skybox.
[pillars_2k.hdr]:
//github.com/google/filament/blob/master/third_party/environments/pillars_2k.hdr
Download [pillars_2k.hdr], then invoke the following command in your terminal.
```bash
@@ -62,19 +62,20 @@ cmgen -x . --format=ktx --size=256 --extract-blur=0.1 pillars_2k.hdr
```
You should now have a `pillars_2k` folder containing a couple KTX files for the IBL and skybox, as
well as a text file with spherical harmonics coefficients. Move the KTX files into your project
folder. You can discard the text file because the IBL KTX contains these coefficients in its
metadata.
well as a text file with spherical harmonics coefficients. You can discard the text file because the
IBL KTX contains these coefficients in its metadata.
## Create HTML and JavaScript
Create a text file called `redball.html` and copy over the HTML that we used in the [previous
tutorial](tutorial_triangle.html). Change the last script tag from `triangle.js` to `redball.js`.
## Create JavaScript
Next, create `redball.js` with the following content.
```js {fragment="root"}
Filament.init([ 'plastic.filamat', 'pillars_2k_ibl.ktx', 'pillars_2k_skybox.ktx' ], () => {
const environ = 'pillars_2k';
const ibl_url = `${environ}/${environ}_ibl.ktx`;
const sky_url = `${environ}/${environ}_skybox.ktx`;
const filamat_url = 'plastic.filamat'
Filament.init([ filamat_url, ibl_url, sky_url ], () => {
// Create some global aliases to enums for convenience.
window.VertexAttribute = Filament.VertexAttribute;
window.AttributeType = Filament.VertexBuffer$AttributeType;
@@ -109,7 +110,7 @@ class App {
this.resize();
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener("resize", this.resize);
window.addEventListener('resize', this.resize);
window.requestAnimationFrame(this.render);
}
@@ -139,14 +140,14 @@ Next let's create a material instance from the package that we built at the begi
Replace the **create material** comment with the following snippet.
```js {fragment="create material"}
const material = engine.createMaterial('plastic.filamat');
const material = engine.createMaterial(filamat_url);
const matinstance = material.createInstance();
const red = [0.8, 0.0, 0.0];
matinstance.setColorParameter("baseColor", Filament.RgbType.sRGB, red);
matinstance.setFloatParameter("roughness", 0.5);
matinstance.setFloatParameter("clearCoat", 1.0);
matinstance.setFloatParameter("clearCoatRoughness", 0.3);
matinstance.setColorParameter('baseColor', Filament.RgbType.sRGB, red);
matinstance.setFloatParameter('roughness', 0.5);
matinstance.setFloatParameter('clearCoat', 1.0);
matinstance.setFloatParameter('clearCoatRoughness', 0.3);
```
The next step is to create a renderable for the sphere. To help with this, we'll use the `IcoSphere`
@@ -232,7 +233,7 @@ const format = Filament.PixelDataFormat.RGBM;
const datatype = Filament.PixelDataType.UBYTE;
// Create a Texture object for the mipmapped cubemap.
const ibl_package = Filament.Buffer(Filament.assets['pillars_2k_ibl.ktx']);
const ibl_package = Filament.Buffer(Filament.assets[ibl_url]);
const iblktx = new Filament.KtxBundle(ibl_package);
const ibltex = Filament.Texture.Builder()
@@ -251,7 +252,7 @@ for (let level = 0; level < iblktx.getNumMipLevels(); ++level) {
}
// Parse the spherical harmonics metadata.
const shstring = iblktx.getMetadata("sh");
const shstring = iblktx.getMetadata('sh');
const shfloats = shstring.split(/\s/, 9 * 3).map(parseFloat);
// Build the IBL object and insert it into the scene.
@@ -268,7 +269,7 @@ Filament provides a JavaScript utility to make this simpler,
simply replace the **create IBL** comment with the following snippet.
```js {fragment="create IBL"}
const indirectLight = engine.createIblFromKtx('pillars_2k_ibl.ktx');
const indirectLight = engine.createIblFromKtx(ibl_url);
indirectLight.setIntensity(50000);
scene.setIndirectLight(indirectLight);
```
@@ -280,7 +281,7 @@ Without a skybox, the reflections on the ball are not representative of its surr
Here's one way to create a texture for the skybox:
```js
const sky_package = Filament.Buffer(Filament.assets['pillars_2k_skybox.ktx']);
const sky_package = Filament.Buffer(Filament.assets[sky_url]);
const skyktx = new Filament.KtxBundle(sky_package);
const skytex = Filament.Texture.Builder()
.width(skyktx.info().pixelWidth)
@@ -300,9 +301,19 @@ Filament provides a Javascript utility to make this easier.
Replace **create skybox** with the following.
```js {fragment="create skybox"}
const skybox = engine.createSkyFromKtx('pillars_2k_skybox.ktx');
const skybox = engine.createSkyFromKtx(sky_url);
scene.setSkybox(skybox);
```
That's it, we now have a shiny red ball floating in an environment! The complete JavaScript
file is available [here](tutorial_redball.js).
That's it, we now have a shiny red ball floating in an environment! The complete JavaScript file is
available [here](tutorial_redball.js).
In the [next tutorial], we'll take a closer look at textures and interaction.
[pillars_2k.hdr]:
//github.com/google/filament/blob/master/third_party/environments/pillars_2k.hdr
[next tutorial]: tutorial_suzanne.html
[previous tutorial]: tutorial_triangle.html
[Filament release]: //github.com/google/filament/releases
[Filament Material System]: https://google.github.io/filament/Materials.md.html
+311
View File
@@ -0,0 +1,311 @@
This tutorial will describe how to create the **suzanne** demo, introducing you to compressed
textures, mipmap generation, asynchronous texture loading, and trackball rotation.
Much like the [previous tutorial], you'll need to use the command-line tools that can be found in
the appropriate [Filament release] for your development machine. In addition to `matc` and `cmgen`,
we'll also be using `filamesh` and `mipgen`.
## Create filamesh file
Filament does not have an asset loading system, but it does provide a simple binary mesh format
called `filamesh` for demonstration purposes. Let's create a filamesh file for suzanne by converting
[this OBJ file]:
```bash
filamesh monkey.obj suzanne.filamesh
```
## Create mipmapped textures
Next, let's create mipmapped KTX files using filament's `mipgen` tool. We'll create compressed and
non-compressed variants for each texture, since not all platforms support the same compression
formats. First copy over the PNG files from the [monkey folder], then do:
```bash
# Create mipmaps for base color and two compressed variants.
mipgen albedo.png albedo.ktx
mipgen --compression=astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
mipgen --compression=s3tc_rgb_dxt1 albedo.png albedo_s3tc.ktx
# Create mipmaps for the normal map and a compressed variant.
mipgen --kernel=NORMALS --linear normal.png normal.ktx
mipgen --kernel=NORMALS --linear --compression=etc_rgb8_normalxyz_40 normal.png normal_etc.ktx
# Create mipmaps for the single-component roughness map and a compressed variant.
mipgen --grayscale roughness.png roughness.ktx
mipgen --grayscale --compression=etc_r11_numeric_40 roughness.png roughness_etc.ktx
# Create mipmaps for the single-component metallic map and a compressed variant.
mipgen --grayscale metallic.png metallic.ktx
mipgen --grayscale --compression=etc_r11_numeric_40 metallic.png metallic_etc.ktx
# Create mipmaps for the single-component occlusion map and a compressed variant.
mipgen --grayscale ao.png ao.ktx
mipgen --grayscale --compression=etc_r11_numeric_40 ao.png ao_etc.ktx
```
For more information on mipgen's arguments and supported formats, do `mipgen --help`.
In a production setting, you'd want to invoke these commands with a script or build system.
## Bake environment map
Much like the [previous tutorial] we need to use Filament's `cmgen` tool to produce cubemap files,
but this time we'll create compressed variants.
Download [syferfontein_18d_clear_2k.hdr], then invoke the following commands in your terminal.
```bash
# Create S3TC variant of the IBL, then rename it to have a _s3tc suffix.
cmgen -x . --format=ktx --size=256 --extract-blur=0.1 --compression=s3tc_rgba_dxt5 \
syferfontein_18d_clear_2k.hdr
cd syfer* ; mv syfer*_ibl.ktx syferfontein_18d_clear_2k_ibl_s3tc.ktx ; cd -
# Create ETC variant of the IBL, then rename it to have a _s3tc suffix.
cmgen -x . --format=ktx --size=256 --extract-blur=0.1 --compression=etc_rgba8_rgba_40 \
syferfontein_18d_clear_2k.hdr
cd syfer* ; mv syfer*_ibl.ktx syferfontein_18d_clear_2k_ibl_etc.ktx ; cd -
# Create small uncompressed Skybox variant, then rename it to have a _tiny suffix.
cmgen -x . --format=ktx --size=64 --extract-blur=0.1 syferfontein_18d_clear_2k.hdr
cd syfer* ; mv syfer*_ibl.ktx syferfontein_18d_clear_2k_skybox_tiny.ktx ; cd -
# Create full-size uncompressed Skybox and IBL
cmgen -x . --format=ktx --size=256 --extract-blur=0.1 syferfontein_18d_clear_2k.hdr
```
## Define textured material
You might recall the `filamat` file we generated in the previous tutorial for red plastic. For this
demo, we'll create a material that uses textures for several parameters.
Create the following textz file call it `textured.mat`. Note that our material definition now
requires a `uv0` attribute.
```text
material {
name : textured,
requires : [ uv0 ],
shadingModel : lit,
parameters : [
{ type : sampler2d, name : albedo },
{ type : sampler2d, name : roughness },
{ type : sampler2d, name : metallic },
{ type : float, name : clearCoat },
{ type : sampler2d, name : normal },
{ type : sampler2d, name : ao }
],
}
fragment {
void material(inout MaterialInputs material) {
material.normal = texture(materialParams_normal, getUV0()).xyz * 2.0 - 1.0;
prepareMaterial(material);
material.baseColor = texture(materialParams_albedo, getUV0());
material.roughness = texture(materialParams_roughness, getUV0()).r;
material.metallic = texture(materialParams_metallic, getUV0()).r;
material.clearCoat = materialParams.clearCoat;
material.ambientOcclusion = texture(materialParams_ao, getUV0()).r;
}
}
```
Next, invoke `matc` as follows.
```bash
matc -O -a opengl -p mobile -o textured.filamat textured.mat
```
You should now have a material archive in your working directory. For the suzanne asset, the normal
map adds scratches, the albedo map paints the eyes white, and so on. For more information on
materials, consult the official document describing the [Filament Material System].
## Create app skeleton
Create a text file called `suzanne.html` and copy over the HTML that we used in the [previous
tutorial]. Change the last script tag from `redball.js` to `suzanne.js`. Next, create `suzanne.js`
with the following content.
```js {fragment="root"}
// TODO: declare asset URLs
Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () => {
window.app = new App(document.getElementsByTagName('canvas')[0]);
});
class App {
constructor(canvas) {
this.canvas = canvas;
this.engine = Filament.Engine.create(canvas);
this.scene = this.engine.createScene();
const material = this.engine.createMaterial(filamat_url);
this.matinstance = material.createInstance();
const filamesh = this.engine.loadFilamesh(filamesh_url, this.matinstance);
this.suzanne = filamesh.renderable;
// TODO: create sky box and IBL
// TODO: initialize gltumble
// TODO: fetch larger assets
this.swapChain = this.engine.createSwapChain();
this.renderer = this.engine.createRenderer();
this.camera = this.engine.createCamera();
this.view = this.engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener('resize', this.resize);
const eye = [0, 0, 4], center = [0, 0, 0], up = [0, 1, 0];
this.camera.lookAt(eye, center, up);
this.resize();
window.requestAnimationFrame(this.render);
}
render() {
// TODO: apply gltumble matrix
this.renderer.render(this.swapChain, this.view);
window.requestAnimationFrame(this.render);
}
resize() {
const dpr = window.devicePixelRatio;
const width = this.canvas.width = window.innerWidth * dpr;
const height = this.canvas.height = window.innerHeight * dpr;
this.view.setViewport([0, 0, width, height]);
const aspect = width / height;
const Fov = Filament.Camera$Fov, fov = aspect < 1 ? Fov.HORIZONTAL : Fov.VERTICAL;
this.camera.setProjectionFov(45, aspect, 1.0, 10.0, fov);
}
}
```
Our app will use 10 downloaded assets, but it only requires 4 of them to be present for `App`
construction. We'll download the other 6 assets after construction. By using a progressive loading
strategy, we can reduce the perceived load time.
Next we need to supply the URLs for various assets. This is actually a bit tricky, because different
clients have different capabilities for compressed textures.
To help you download only the texture assets that you need, Filament provides a
`getSupportedFormatSuffix` function. This takes a space-separated list of desired format types
(`etc`, `s3tc`, or `astc`) that the app developer knows is available from the server. The function
performs an intersection of the *desired* set with the *supported* set, then returns an appropriate
string -- which might be empty.
In our case, we know that our web server will have `etc` and `s3tc` variants for the IBL, `astc` and
`s3tc` variants for albedo, and `etc` variants for the other textures. The uncompressed variants
(empty string) are always available as a last resort. Go ahead and replace the **declare asset
URLs** comment with the following snippet.
```js {fragment="declare asset URLs"}
const ibl_suffix = Filament.getSupportedFormatSuffix('etc s3tc');
const albedo_suffix = Filament.getSupportedFormatSuffix('astc s3tc');
const texture_suffix = Filament.getSupportedFormatSuffix('etc');
const environ = 'syferfontein_18d_clear_2k'
const ibl_url = `${environ}/${environ}_ibl${ibl_suffix}.ktx`;
const sky_small_url = `${environ}/${environ}_skybox_tiny.ktx`;
const sky_large_url = `${environ}/${environ}_skybox.ktx`;
const albedo_url = `albedo${albedo_suffix}.ktx`;
const ao_url = `ao${texture_suffix}.ktx`;
const metallic_url = `metallic${texture_suffix}.ktx`;
const normal_url = `normal${texture_suffix}.ktx`;
const roughness_url = `roughness${texture_suffix}.ktx`;
const filamat_url = 'textured.filamat';
const filamesh_url = 'suzanne.filamesh';
```
## Create skybox and IBL
Next, let's create the low-resolution skybox and IBL in the `App` constructor.
```js {fragment="create sky box and IBL"}
this.skybox = this.engine.createSkyFromKtx(sky_small_url);
this.scene.setSkybox(this.skybox);
this.indirectLight = this.engine.createIblFromKtx(ibl_url);
this.indirectLight.setIntensity(100000);
this.scene.setIndirectLight(this.indirectLight);
```
This allows users to see a reasonable background fairly quickly, before larger assets have finished
loading in.
## Fetch assets asychronously
Next we'll invoke the `Filament.fetch` function from within the app constructor. This function is
very similar to `Filament.init`. It takes a list of asset URLs and a callback function that triggers
when the assets have finished downloading.
In our callback, we'll make several `setTextureParameter` calls on the material instance, then we'll
recreate the skybox using a higher-resolution texture. As a last step we unhide the renderable that
was created in the app constructor.
```js {fragment="fetch larger assets"}
Filament.fetch([sky_large_url, albedo_url, roughness_url, metallic_url, normal_url, ao_url], () => {
const albedo = this.engine.createTextureFromKtx(albedo_url, {srgb: true});
const roughness = this.engine.createTextureFromKtx(roughness_url);
const metallic = this.engine.createTextureFromKtx(metallic_url);
const normal = this.engine.createTextureFromKtx(normal_url);
const ao = this.engine.createTextureFromKtx(ao_url);
const sampler = new Filament.TextureSampler(
Filament.MinFilter.LINEAR_MIPMAP_LINEAR,
Filament.MagFilter.LINEAR,
Filament.WrapMode.CLAMP_TO_EDGE);
this.matinstance.setTextureParameter('albedo', albedo, sampler);
this.matinstance.setTextureParameter('roughness', roughness, sampler);
this.matinstance.setTextureParameter('metallic', metallic, sampler);
this.matinstance.setTextureParameter('normal', normal, sampler);
this.matinstance.setTextureParameter('ao', ao, sampler);
// Replace low-res skybox with high-res skybox.
this.engine.destroySkybox(this.skybox);
this.skybox = this.engine.createSkyFromKtx(sky_large_url);
this.scene.setSkybox(this.skybox);
this.scene.addEntity(this.suzanne);
});
```
## Introduce trackball rotation
Add the following script tag to your HTML file. This imports a small third-party library that
listens for drag events and computes a rotation matrix.
```html
<script src="https://unpkg.com/gltumble"></script>
```
Next, replace the **initialize gltumble** and **apply gltumble matrix** comments with the following
two code snippets.
```js {fragment="initialize gltumble"}
this.trackball = new Trackball(canvas, {startSpin: 0.035});
```
```js {fragment="apply gltumble matrix"}
const tcm = this.engine.getTransformManager();
const inst = tcm.getInstance(this.suzanne);
tcm.setTransform(inst, this.trackball.getMatrix());
inst.delete();
```
That's it, we now have a fast-loading interactive demo. The complete JavaScript file is available
[here](tutorial_suzanne.js).
[Filament release]: //github.com/google/filament/releases
[previous tutorial]: tutorial_redball.html
[Filament Material System]: https://google.github.io/filament/Materials.md.html
[this OBJ file]: https://github.com/google/filament/blob/master/assets/models/monkey/monkey.obj
[monkey folder]: https://github.com/google/filament/blob/master/assets/models/monkey
[syferfontein_18d_clear_2k.hdr]:
//github.com/google/filament/blob/master/third_party/environments/syferfontein_18d_clear_2k.hdr
+11 -4
View File
@@ -39,7 +39,7 @@ class App {
// TODO: create entities
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener("resize", this.resize);
window.addEventListener('resize', this.resize);
window.requestAnimationFrame(this.render);
}
render() {
@@ -71,16 +71,20 @@ that define a PBR material. We'll learn more about material packages in the next
## Spawn a local server
Because of CORS restrictions, your web app cannot fetch the material package directly from the
file system. One way around this is to create a temporary server using Python:
file system. One way around this is to create a temporary server using Python or node:
```bash
python3 -m http.server # Python 3
python -m SimpleHTTPServer # Python 2.7
npx http-server -p 8000 # nodejs
```
To see if this works, navigate to [http://localhost:8000](http://localhost:8000) and check if you
can load the page without any errors appearing in the developer console.
Take care not to use Python's simple server in production since it does not serve WebAssembly files
with the correct MIME type.
## Create the Engine and Scene
We now have a basic skeleton that can respond to paint and resize events. Let's start adding
@@ -257,5 +261,8 @@ this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
```
You should now have a spinning triangle! The completed JavaScript is available
[here](tutorial_triangle.js). In the next tutorial, we'll take a closer look at Filament
materials and 3D rendering.
[here](tutorial_triangle.js).
In the [next tutorial], we'll take a closer look at Filament materials and 3D rendering.
[next tutorial]: tutorial_redball.html
+9 -2
View File
@@ -90,6 +90,7 @@ add_mesh("third_party/shader_ball/shader_ball.obj" "shader_ball.filamesh")
# Generate IBL and skybox images using cmgen.
set(CMGEN_ARGS -x . --format=ktx --size=256 --extract-blur=0.1)
set(CMGEN_ARGS_TINY -x . --format=ktx --size=64 --extract-blur=0.1)
set(CMGEN_ARGS_S3TC ${CMGEN_ARGS} --compression=s3tc_rgba_dxt5)
set(CMGEN_ARGS_ETC ${CMGEN_ARGS} --compression=etc_rgba8_rgba_40)
function(add_envmap SOURCE TARGET)
@@ -103,12 +104,14 @@ function(add_envmap SOURCE TARGET)
set(target_envmap_etc "${SERVER_DIR}/${TARGET}/${TARGET}_ibl_etc.ktx")
set(target_envmap_s3tc "${SERVER_DIR}/${TARGET}/${TARGET}_ibl_s3tc.ktx")
set(target_skyboxes ${target_skyboxes} ${target_skybox} PARENT_SCOPE)
set(target_skybox_tiny "${SERVER_DIR}/${TARGET}/${TARGET}_skybox_tiny.ktx")
set(target_skyboxes ${target_skyboxes} ${target_skybox} ${target_skybox_tiny} PARENT_SCOPE)
set(target_envmaps ${target_envmaps}
${target_envmap} ${target_envmap_etc} ${target_envmap_s3tc} PARENT_SCOPE)
add_custom_command(OUTPUT ${target_skybox}
add_custom_command(OUTPUT ${target_skybox} ${target_skybox_tiny}
${target_envmap} ${target_envmap_etc} ${target_envmap_s3tc}
# First create an S3TC-encoded envmap, then rename it.
@@ -119,6 +122,10 @@ function(add_envmap SOURCE TARGET)
COMMAND cmgen ${CMGEN_ARGS_ETC} ${source_envmap}
COMMAND mv ${target_envmap} ${target_envmap_etc}
# Create a low-resolution skybox, then rename it.
COMMAND cmgen ${CMGEN_ARGS_TINY} ${source_envmap}
COMMAND mv ${target_skybox} ${target_skybox_tiny}
# Finally, create KTX files for the uncompressed envmap.
COMMAND cmgen ${CMGEN_ARGS} ${source_envmap}