258 lines
26 KiB
HTML
258 lines
26 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en"><head>
|
|
<link href="https://google.github.io/filament/favicon.png" rel="icon" type="image/x-icon" />
|
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
|
|
<link href="main.css" rel="stylesheet" type="text/css">
|
|
</head>
|
|
<body class="verbiage">
|
|
<div class="demo_frame"><iframe src="demo_suzanne.html"></iframe><a href="demo_suzanne.html">🔗</a></div>
|
|
<p>This tutorial will describe how to create the <strong>suzanne</strong> demo, introducing you to compressed
|
|
textures, mipmap generation, asynchronous texture loading, and trackball rotation.</p>
|
|
<p>Much like the <a href="tutorial_redball.html">previous tutorial</a>, you'll need to use the command-line tools that can be found in
|
|
the appropriate <a href="//github.com/google/filament/releases">Filament release</a> for your development machine. In addition to <code>matc</code> and <code>cmgen</code>,
|
|
we'll also be using <code>filamesh</code> and <code>mipgen</code>.</p>
|
|
<h2>Create filamesh file</h2>
|
|
<p>Filament does not have an asset loading system, but it does provide a binary mesh format
|
|
called <code>filamesh</code> for simple use cases. Let's create a compressed filamesh file for suzanne by
|
|
converting <a href="https://github.com/google/filament/blob/main/assets/models/monkey/monkey.obj">this OBJ file</a>:</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>filamesh --compress monkey.obj suzanne.filamesh
|
|
</pre></div>
|
|
|
|
<h2>Create mipmapped textures</h2>
|
|
<p>Next, let's create mipmapped KTX files using filament's <code>mipgen</code> 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 <a href="https://github.com/google/filament/blob/main/assets/models/monkey">monkey folder</a>, then do:</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic"># Create mipmaps for base color and two compressed variants.</span>
|
|
mipgen albedo.png albedo.ktx
|
|
mipgen --compression<span style="color: #666666">=</span>astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
|
|
mipgen --compression<span style="color: #666666">=</span>s3tc_rgb_dxt1 albedo.png albedo_s3tc.ktx
|
|
|
|
<span style="color: #408080; font-style: italic"># Create mipmaps for the normal map and a compressed variant.</span>
|
|
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear normal.png normal.ktx
|
|
mipgen --strip-alpha --kernel<span style="color: #666666">=</span>NORMALS --linear --compression<span style="color: #666666">=</span>etc_rgb8_normalxyz_40 <span style="color: #BB6622; font-weight: bold">\</span>
|
|
normal.png normal_etc.ktx
|
|
|
|
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component roughness map and a compressed variant.</span>
|
|
mipgen --grayscale roughness.png roughness.ktx
|
|
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 roughness.png roughness_etc.ktx
|
|
|
|
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component metallic map and a compressed variant.</span>
|
|
mipgen --grayscale metallic.png metallic.ktx
|
|
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 metallic.png metallic_etc.ktx
|
|
|
|
<span style="color: #408080; font-style: italic"># Create mipmaps for the single-component occlusion map and a compressed variant.</span>
|
|
mipgen --grayscale ao.png ao.ktx
|
|
mipgen --grayscale --compression<span style="color: #666666">=</span>etc_r11_numeric_40 ao.png ao_etc.ktx
|
|
</pre></div>
|
|
|
|
<p>For more information on mipgen's arguments and supported formats, do <code>mipgen --help</code>.</p>
|
|
<p>In a production setting, you'd want to invoke these commands with a script or build system.</p>
|
|
<h2>Bake environment map</h2>
|
|
<p>Much like the <a href="tutorial_redball.html">previous tutorial</a> we need to use Filament's <code>cmgen</code> tool to produce cubemap files.</p>
|
|
<p>Download <a href="//github.com/google/filament/blob/main/third_party/environments/venetian_crossroads_2k.hdr">venetian_crossroads_2k.hdr</a>, then invoke the following commands in your terminal.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=64</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
|
|
<span style="color: #008000">cd</span> venetian* ; mv venetian*_ibl.ktx venetian_crossroads_2k_skybox_tiny.ktx ; <span style="color: #008000">cd</span> -
|
|
|
|
cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
|
|
cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
|
|
cmgen -x . --format<span style="color: #666666">=</span>ktx --size<span style="color: #666666">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 venetian_crossroads_2k.hdr
|
|
</pre></div>
|
|
|
|
<h2>Define textured material</h2>
|
|
<p>You might recall the <code>filamat</code> file we generated in the previous tutorial for red plastic. For this
|
|
demo, we'll create a material that uses textures for several parameters.</p>
|
|
<p>Create the following text file and call it <code>textured.mat</code>. Note that our material definition now
|
|
requires a <code>uv0</code> attribute.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>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;
|
|
}
|
|
}
|
|
</pre></div>
|
|
|
|
<p>Next, invoke <code>matc</code> as follows.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>matc -a opengl -p mobile -o textured.filamat textured.mat
|
|
</pre></div>
|
|
|
|
<p>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 <a href="https://google.github.io/filament/Materials.md.html">Filament Material System</a>.</p>
|
|
<h2>Create app skeleton</h2>
|
|
<p>Create a text file called <code>suzanne.html</code> and copy over the HTML that we used in the <a href="tutorial_redball.html">previous
|
|
tutorial</a>. Change the last script tag from <code>redball.js</code> to <code>suzanne.js</code>. Next, create <code>suzanne.js</code>
|
|
with the following content.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic">// TODO: declare asset URLs</span>
|
|
|
|
Filament.init([ filamat_url, filamesh_url, sky_small_url, ibl_url ], () => {
|
|
<span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> App(<span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">'canvas'</span>)[<span style="color: #666666">0</span>]);
|
|
});
|
|
|
|
<span style="color: #008000; font-weight: bold">class</span> App {
|
|
constructor(canvas) {
|
|
<span style="color: #008000; font-weight: bold">this</span>.canvas <span style="color: #666666">=</span> canvas;
|
|
<span style="color: #008000; font-weight: bold">this</span>.engine <span style="color: #666666">=</span> Filament.Engine.create(canvas);
|
|
<span style="color: #008000; font-weight: bold">this</span>.scene <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createScene();
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> material <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createMaterial(filamat_url);
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance <span style="color: #666666">=</span> material.createInstance();
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> filamesh <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.loadFilamesh(filamesh_url, <span style="color: #008000; font-weight: bold">this</span>.matinstance);
|
|
<span style="color: #008000; font-weight: bold">this</span>.suzanne <span style="color: #666666">=</span> filamesh.renderable;
|
|
|
|
<span style="color: #408080; font-style: italic">// TODO: create sky box and IBL</span>
|
|
<span style="color: #408080; font-style: italic">// TODO: initialize gltumble</span>
|
|
<span style="color: #408080; font-style: italic">// TODO: fetch larger assets</span>
|
|
|
|
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSwapChain();
|
|
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createRenderer();
|
|
<span style="color: #008000; font-weight: bold">this</span>.camera <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createCamera(Filament.EntityManager.get().create());
|
|
<span style="color: #008000; font-weight: bold">this</span>.view <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createView();
|
|
<span style="color: #008000; font-weight: bold">this</span>.view.setCamera(<span style="color: #008000; font-weight: bold">this</span>.camera);
|
|
<span style="color: #008000; font-weight: bold">this</span>.view.setScene(<span style="color: #008000; font-weight: bold">this</span>.scene);
|
|
<span style="color: #008000; font-weight: bold">this</span>.render <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.render.bind(<span style="color: #008000; font-weight: bold">this</span>);
|
|
<span style="color: #008000; font-weight: bold">this</span>.resize <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.resize.bind(<span style="color: #008000; font-weight: bold">this</span>);
|
|
<span style="color: #008000">window</span>.addEventListener(<span style="color: #BA2121">'resize'</span>, <span style="color: #008000; font-weight: bold">this</span>.resize);
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> eye <span style="color: #666666">=</span> [<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">4</span>], center <span style="color: #666666">=</span> [<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>], up <span style="color: #666666">=</span> [<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, <span style="color: #666666">0</span>];
|
|
<span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye, center, up);
|
|
|
|
<span style="color: #008000; font-weight: bold">this</span>.resize();
|
|
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
|
}
|
|
|
|
render() {
|
|
<span style="color: #408080; font-style: italic">// TODO: apply gltumble matrix</span>
|
|
<span style="color: #008000; font-weight: bold">this</span>.renderer.render(<span style="color: #008000; font-weight: bold">this</span>.swapChain, <span style="color: #008000; font-weight: bold">this</span>.view);
|
|
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
|
|
}
|
|
|
|
resize() {
|
|
<span style="color: #008000; font-weight: bold">const</span> dpr <span style="color: #666666">=</span> <span style="color: #008000">window</span>.devicePixelRatio;
|
|
<span style="color: #008000; font-weight: bold">const</span> width <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.canvas.width <span style="color: #666666">=</span> <span style="color: #008000">window</span>.innerWidth <span style="color: #666666">*</span> dpr;
|
|
<span style="color: #008000; font-weight: bold">const</span> height <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.canvas.height <span style="color: #666666">=</span> <span style="color: #008000">window</span>.innerHeight <span style="color: #666666">*</span> dpr;
|
|
<span style="color: #008000; font-weight: bold">this</span>.view.setViewport([<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, width, height]);
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> aspect <span style="color: #666666">=</span> width <span style="color: #666666">/</span> height;
|
|
<span style="color: #008000; font-weight: bold">const</span> Fov <span style="color: #666666">=</span> Filament.Camera$Fov, fov <span style="color: #666666">=</span> aspect <span style="color: #666666"><</span> <span style="color: #666666">1</span> <span style="color: #666666">?</span> Fov.HORIZONTAL <span style="color: #666666">:</span> Fov.VERTICAL;
|
|
<span style="color: #008000; font-weight: bold">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>, aspect, <span style="color: #666666">1.0</span>, <span style="color: #666666">10.0</span>, fov);
|
|
}
|
|
}
|
|
</pre></div>
|
|
|
|
<p>Our app will only require a subset of assets to be present for <code>App</code> construction. We'll download
|
|
the other assets after construction. By using a progressive loading strategy, we can reduce the
|
|
perceived load time.</p>
|
|
<p>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.</p>
|
|
<p>To help you download only the texture assets that you need, Filament provides a
|
|
<code>getSupportedFormatSuffix</code> function. This takes a space-separated list of desired format types
|
|
(<code>etc</code>, <code>s3tc</code>, or <code>astc</code>) that the app developer knows is available from the server. The function
|
|
performs an intersection of the <em>desired</em> set with the <em>supported</em> set, then returns an appropriate
|
|
string -- which might be empty.</p>
|
|
<p>In our case, we know that our web server will have <code>astc</code> and <code>s3tc</code> variants for albedo, and <code>etc</code>
|
|
variants for the other textures. The uncompressed variants (empty string) are always available as a
|
|
last resort. Go ahead and replace the <strong>declare asset URLs</strong> comment with the following snippet.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> albedo_suffix <span style="color: #666666">=</span> Filament.getSupportedFormatSuffix(<span style="color: #BA2121">'astc s3tc'</span>);
|
|
<span style="color: #008000; font-weight: bold">const</span> texture_suffix <span style="color: #666666">=</span> Filament.getSupportedFormatSuffix(<span style="color: #BA2121">'etc'</span>);
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> environ <span style="color: #666666">=</span> <span style="color: #BA2121">'venetian_crossroads_2k'</span>
|
|
<span style="color: #008000; font-weight: bold">const</span> ibl_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_ibl.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> sky_small_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox_tiny.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> sky_large_url <span style="color: #666666">=</span> <span style="color: #BA2121">`</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">/</span><span style="color: #BB6688; font-weight: bold">${</span>environ<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">_skybox.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> albedo_url <span style="color: #666666">=</span> <span style="color: #BA2121">`albedo</span><span style="color: #BB6688; font-weight: bold">${</span>albedo_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> ao_url <span style="color: #666666">=</span> <span style="color: #BA2121">`ao</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> metallic_url <span style="color: #666666">=</span> <span style="color: #BA2121">`metallic</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> normal_url <span style="color: #666666">=</span> <span style="color: #BA2121">`normal</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> roughness_url <span style="color: #666666">=</span> <span style="color: #BA2121">`roughness</span><span style="color: #BB6688; font-weight: bold">${</span>texture_suffix<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BA2121">.ktx`</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> filamat_url <span style="color: #666666">=</span> <span style="color: #BA2121">'textured.filamat'</span>;
|
|
<span style="color: #008000; font-weight: bold">const</span> filamesh_url <span style="color: #666666">=</span> <span style="color: #BA2121">'suzanne.filamesh'</span>;
|
|
</pre></div>
|
|
|
|
<h2>Create skybox and IBL</h2>
|
|
<p>Next, let's create the low-resolution skybox and IBL in the <code>App</code> constructor.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.skybox <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx(sky_small_url);
|
|
<span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
|
|
<span style="color: #008000; font-weight: bold">this</span>.indirectLight <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createIblFromKtx(ibl_url);
|
|
<span style="color: #008000; font-weight: bold">this</span>.indirectLight.setIntensity(<span style="color: #666666">100000</span>);
|
|
<span style="color: #008000; font-weight: bold">this</span>.scene.setIndirectLight(<span style="color: #008000; font-weight: bold">this</span>.indirectLight);
|
|
</pre></div>
|
|
|
|
<p>This allows users to see a reasonable background fairly quickly, before larger assets have finished
|
|
loading in.</p>
|
|
<h2>Fetch assets asychronously</h2>
|
|
<p>Next we'll invoke the <code>Filament.fetch</code> function from within the app constructor. This function is
|
|
very similar to <code>Filament.init</code>. It takes a list of asset URLs and a callback function that triggers
|
|
when the assets have finished downloading.</p>
|
|
<p>In our callback, we'll make several <code>setTextureParameter</code> 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.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>Filament.fetch([sky_large_url, albedo_url, roughness_url, metallic_url, normal_url, ao_url], () => {
|
|
<span style="color: #008000; font-weight: bold">const</span> albedo <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx(albedo_url, {srgb<span style="color: #666666">:</span> <span style="color: #008000; font-weight: bold">true</span>});
|
|
<span style="color: #008000; font-weight: bold">const</span> roughness <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx(roughness_url);
|
|
<span style="color: #008000; font-weight: bold">const</span> metallic <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx(metallic_url);
|
|
<span style="color: #008000; font-weight: bold">const</span> normal <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx(normal_url);
|
|
<span style="color: #008000; font-weight: bold">const</span> ao <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createTextureFromKtx(ao_url);
|
|
|
|
<span style="color: #008000; font-weight: bold">const</span> sampler <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Filament.TextureSampler(
|
|
Filament.MinFilter.LINEAR_MIPMAP_LINEAR,
|
|
Filament.MagFilter.LINEAR,
|
|
Filament.WrapMode.CLAMP_TO_EDGE);
|
|
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'albedo'</span>, albedo, sampler);
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'roughness'</span>, roughness, sampler);
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'metallic'</span>, metallic, sampler);
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'normal'</span>, normal, sampler);
|
|
<span style="color: #008000; font-weight: bold">this</span>.matinstance.setTextureParameter(<span style="color: #BA2121">'ao'</span>, ao, sampler);
|
|
|
|
<span style="color: #408080; font-style: italic">// Replace low-res skybox with high-res skybox.</span>
|
|
<span style="color: #008000; font-weight: bold">this</span>.engine.destroySkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
|
|
<span style="color: #008000; font-weight: bold">this</span>.skybox <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.createSkyFromKtx(sky_large_url);
|
|
<span style="color: #008000; font-weight: bold">this</span>.scene.setSkybox(<span style="color: #008000; font-weight: bold">this</span>.skybox);
|
|
|
|
<span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.suzanne);
|
|
});
|
|
</pre></div>
|
|
|
|
<h2>Introduce trackball rotation</h2>
|
|
<p>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.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">"//unpkg.com/gltumble"</span>></<span style="color: #008000; font-weight: bold">script</span>>
|
|
</pre></div>
|
|
|
|
<p>Next, replace the <strong>initialize gltumble</strong> and <strong>apply gltumble matrix</strong> comments with the following
|
|
two code snippets.</p>
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.trackball <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Trackball(canvas, {startSpin<span style="color: #666666">:</span> <span style="color: #666666">0.035</span>});
|
|
</pre></div>
|
|
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> tcm <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine.getTransformManager();
|
|
<span style="color: #008000; font-weight: bold">const</span> inst <span style="color: #666666">=</span> tcm.getInstance(<span style="color: #008000; font-weight: bold">this</span>.suzanne);
|
|
tcm.setTransform(inst, <span style="color: #008000; font-weight: bold">this</span>.trackball.getMatrix());
|
|
inst.<span style="color: #008000; font-weight: bold">delete</span>();
|
|
</pre></div>
|
|
|
|
<p>That's it, we now have a fast-loading interactive demo. The complete JavaScript file is available
|
|
<a href="tutorial_suzanne.js">here</a>.</p>
|
|
|
|
</body>
|
|
</html>
|