Publish Hugo site and web tutorials.

This performs the steps described in site/README in order to publish
the Hugo site to GitHub Pages:

    https://google.github.io/filament
This commit is contained in:
Philip Rideout
2018-11-13 11:24:41 -08:00
parent 904573b374
commit 0faf7bbcb6
67 changed files with 3726 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 Page not found &middot; Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<h1>404: Page not found</h1>
<p class="lead">Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. <a href="https://google.github.io/filament/">Head back home</a> to try finding it again.</p>
</main>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

+70
View File
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Categories &middot; Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="https://google.github.io/filament/categories/index.xml" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<ul class="posts">
</ul>
</main>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Categories on Filament</title>
<link>https://google.github.io/filament/categories/</link>
<description>Recent content in Categories on Filament</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<atom:link href="https://google.github.io/filament/categories/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>
+283
View File
@@ -0,0 +1,283 @@
/*
* __ __
* /\ \ /\ \
* \ \ \___ __ __ \_\ \ __
* \ \ _ `\/\ \/\ \ /'_` \ /'__`\
* \ \ \ \ \ \ \_\ \/\ \_\ \/\ __/
* \ \_\ \_\/`____ \ \___,_\ \____\
* \/_/\/_/`/___/> \/__,_ /\/____/
* /\___/
* \/__/
*
* Designed, built, and released under MIT license by @mdo. Learn more at
* https://github.com/poole/hyde.
*/
/*
* Contents
*
* Global resets
* Sidebar
* Container
* Reverse layout
* Themes
*/
/*
* Global resets
*
* Update the foundational and global aspects of the page.
*/
html {
font-family: "Open Sans", Helvetica, Arial, sans-serif;
}
@media (min-width: 48em) {
html {
font-size: 16px;
}
}
@media (min-width: 58em) {
html {
font-size: 20px;
}
}
/*
* Sidebar
*
* Flexible banner for housing site name, intro, and "footer" content. Starts
* out above content in mobile and later moves to the side with wider viewports.
*/
.sidebar {
text-align: center;
padding: 2rem 1rem;
color: rgba(255,255,255,.5);
background-color: #202020;
}
@media (min-width: 48em) {
.sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: 18rem;
text-align: left;
}
}
/* Sidebar links */
.sidebar a {
color: #fff;
}
/* About section */
.sidebar-about h1 {
color: #fff;
margin-top: 0;
font-family: "Abril Fatface", serif;
font-size: 3.25rem;
}
/* Sidebar nav */
.sidebar-nav {
padding-left: 0;
list-style: none;
}
.sidebar-nav-item {
display: block;
}
a.sidebar-nav-item:hover,
a.sidebar-nav-item:focus {
text-decoration: underline;
}
.sidebar-nav-item.active {
font-weight: bold;
}
/* Sticky sidebar
*
* Add the `sidebar-sticky` class to the sidebar's container to affix it the
* contents to the bottom of the sidebar in tablets and up.
*/
@media (min-width: 48em) {
.sidebar-sticky {
position: absolute;
right: 1rem;
bottom: 1rem;
left: 1rem;
}
}
/* Container
*
* Align the contents of the site above the proper threshold with some margin-fu
* with a 25%-wide `.sidebar`.
*/
.content {
padding-top: 4rem;
padding-bottom: 4rem;
}
@media (min-width: 48em) {
.content {
max-width: 38rem;
margin-left: 20rem;
margin-right: 2rem;
}
}
@media (min-width: 64em) {
.content {
margin-left: 22rem;
margin-right: 4rem;
}
}
/*
* Reverse layout
*
* Flip the orientation of the page by placing the `.sidebar` on the right.
*/
@media (min-width: 48em) {
.layout-reverse .sidebar {
left: auto;
right: 0;
}
.layout-reverse .content {
margin-left: 2rem;
margin-right: 20rem;
}
}
@media (min-width: 64em) {
.layout-reverse .content {
margin-left: 4rem;
margin-right: 22rem;
}
}
/*
* Themes
*
* As of v1.1, Hyde includes optional themes to color the sidebar and links
* within blog posts. To use, add the class of your choosing to the `body`.
*/
/* Base16 (http://chriskempson.github.io/base16/#default) */
/* Red */
.theme-base-08 .sidebar {
background-color: #ac4142;
}
.theme-base-08 .content a,
.theme-base-08 .related-posts li a:hover {
color: #ac4142;
}
/* Orange */
.theme-base-09 .sidebar {
background-color: #d28445;
}
.theme-base-09 .content a,
.theme-base-09 .related-posts li a:hover {
color: #d28445;
}
/* Yellow */
.theme-base-0a .sidebar {
background-color: #f4bf75;
}
.theme-base-0a .content a,
.theme-base-0a .related-posts li a:hover {
color: #f4bf75;
}
/* Green */
.theme-base-0b .sidebar {
background-color: #90a959;
}
.theme-base-0b .content a,
.theme-base-0b .related-posts li a:hover {
color: #90a959;
}
/* Cyan */
.theme-base-0c .sidebar {
background-color: #75b5aa;
}
.theme-base-0c .content a,
.theme-base-0c .related-posts li a:hover {
color: #75b5aa;
}
/* Light Gray */
.theme-base-0d .sidebar {
background-color: #d0d0d0;
}
.theme-base-0d .content a,
.theme-base-0d .related-posts li a:hover {
color: #7080d0;
}
.theme-base-0d .lead {
color: black;
}
.theme-base-0d .sidebar a {
color: #34a;
}
.content.container {
padding-top: 32px;
}
.lightbulb {
max-height: 100%;
display: inline;
}
@media (min-width: 48em) {
.lightbulb {
margin-left: -10px;
}
}
iframe {
border: 0;
width: 100%;
margin-bottom: 15px;
}
/* Magenta */
.theme-base-0e .sidebar {
background-color: #aa759f;
}
.theme-base-0e .content a,
.theme-base-0e .related-posts li a:hover {
color: #aa759f;
}
/* Brown */
.theme-base-0f .sidebar {
background-color: #8f5536;
}
.theme-base-0f .content a,
.theme-base-0f .related-posts li a:hover {
color: #8f5536;
}
.post li {
list-style-type: none;
}
+403
View File
@@ -0,0 +1,403 @@
/*
* ___
* /\_ \
* _____ ___ ___\//\ \ __
* /\ '__`\ / __`\ / __`\\ \ \ /'__`\
* \ \ \_\ \/\ \_\ \/\ \_\ \\_\ \_/\ __/
* \ \ ,__/\ \____/\ \____//\____\ \____\
* \ \ \/ \/___/ \/___/ \/____/\/____/
* \ \_\
* \/_/
*
* Designed, built, and released under MIT license by @mdo. Learn more at
* https://github.com/poole/poole.
*/
/*
* Contents
*
* Body resets
* Custom type
* Messages
* Container
* Masthead
* Posts and pages
* Pagination
* Reverse layout
* Themes
*/
/*
* Body resets
*
* Update the foundational and global aspects of the page.
*/
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
}
@media (min-width: 38em) {
html {
font-size: 20px;
}
}
body {
color: #515151;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
/* No `:visited` state is required by default (browsers will use `a`) */
a {
color: #268bd2;
text-decoration: none;
}
/* `:focus` is linked to `:hover` for basic accessibility */
a:hover,
a:focus {
text-decoration: underline;
}
/* Headings */
h1, h2, h3, h4, h5, h6 {
margin-bottom: .5rem;
font-weight: bold;
line-height: 1.25;
color: #313131;
text-rendering: optimizeLegibility;
}
h1 {
font-size: 2rem;
}
h2 {
margin-top: 1rem;
font-size: 1.5rem;
}
h3 {
margin-top: 1.5rem;
font-size: 1.25rem;
}
h4, h5, h6 {
margin-top: 1rem;
font-size: 1rem;
}
/* Body text */
p {
margin-top: 0;
margin-bottom: 1rem;
}
strong {
color: #303030;
}
/* Lists */
ul, ol, dl {
margin-top: 0;
margin-bottom: 1rem;
}
dt {
font-weight: bold;
}
dd {
margin-bottom: .5rem;
}
/* Misc */
hr {
position: relative;
margin: 1.5rem 0;
border: 0;
border-top: 1px solid #eee;
border-bottom: 1px solid #fff;
}
abbr {
font-size: 85%;
font-weight: bold;
color: #555;
text-transform: uppercase;
}
abbr[title] {
cursor: help;
border-bottom: 1px dotted #e5e5e5;
}
/* Code */
code,
pre {
font-family: Menlo, Monaco, "Courier New", monospace;
}
code {
padding: .25em .5em;
font-size: 85%;
color: #bf616a;
background-color: #f9f9f9;
border-radius: 3px;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
padding: 1rem;
font-size: .8rem;
line-height: 1.4;
white-space: pre;
white-space: pre-wrap;
word-break: break-all;
word-wrap: break-word;
background-color: #f9f9f9;
}
pre code {
padding: 0;
font-size: 100%;
color: inherit;
background-color: transparent;
}
.highlight {
margin-bottom: 1rem;
border-radius: 4px;
}
.highlight pre {
margin-bottom: 0;
}
/* Quotes */
blockquote {
padding: .5rem 1rem;
margin: .8rem 0;
color: #7a7a7a;
border-left: .25rem solid #e5e5e5;
}
blockquote p:last-child {
margin-bottom: 0;
}
@media (min-width: 30em) {
blockquote {
padding-right: 5rem;
padding-left: 1.25rem;
}
}
img {
display: block;
margin: 0 0 1rem;
border-radius: 5px;
max-width: 100%;
}
/* Tables */
table {
margin-bottom: 1rem;
width: 100%;
border: 1px solid #e5e5e5;
border-collapse: collapse;
}
td,
th {
padding: .25rem .5rem;
border: 1px solid #e5e5e5;
}
tbody tr:nth-child(odd) td,
tbody tr:nth-child(odd) th {
background-color: #f9f9f9;
}
/*
* Custom type
*
* Extend paragraphs with `.lead` for larger introductory text.
*/
.lead {
font-size: 1.25rem;
font-weight: 300;
}
/*
* Messages
*
* Show alert messages to users. You may add it to single elements like a `<p>`,
* or to a parent if there are multiple elements to show.
*/
.message {
margin-bottom: 1rem;
padding: 1rem;
color: #717171;
background-color: #f9f9f9;
}
/*
* Container
*
* Center the page content.
*/
.container {
max-width: 38rem;
padding-left: 1rem;
padding-right: 1rem;
margin-left: auto;
margin-right: auto;
}
/*
* Masthead
*
* Super small header above the content for site name and short description.
*/
.masthead {
padding-top: 1rem;
padding-bottom: 1rem;
margin-bottom: 3rem;
}
.masthead-title {
margin-top: 0;
margin-bottom: 0;
color: #505050;
}
.masthead-title a {
color: #505050;
}
.masthead-title small {
font-size: 75%;
font-weight: 400;
color: #c0c0c0;
letter-spacing: 0;
}
/*
* Posts and pages
*
* Each post is wrapped in `.post` and is used on default and post layouts. Each
* page is wrapped in `.page` and is only used on the page layout.
*/
.page,
.post {
margin-bottom: 4em;
}
/* Blog post or page title */
.page-title,
.post-title,
.post-title a {
color: #303030;
}
.page-title,
.post-title {
margin-top: 0;
}
/* Meta data line below post title */
.post-date {
display: block;
margin-top: -.5rem;
margin-bottom: 1rem;
color: #9a9a9a;
}
/* Related posts */
.related {
padding-top: 2rem;
padding-bottom: 2rem;
border-top: 1px solid #eee;
}
.related-posts {
padding-left: 0;
list-style: none;
}
.related-posts h3 {
margin-top: 0;
}
.related-posts li small {
font-size: 75%;
color: #999;
}
.related-posts li a:hover {
color: #268bd2;
text-decoration: none;
}
.related-posts li a:hover small {
color: inherit;
}
/*
* Pagination
*
* Super lightweight (HTML-wise) blog pagination. `span`s are provide for when
* there are no more previous or next posts to show.
*/
.pagination {
overflow: hidden; /* clearfix */
margin-left: -1rem;
margin-right: -1rem;
font-family: "Open Sans", Helvetica, Arial, sans-serif;
color: #ccc;
text-align: center;
}
/* Pagination items can be `span`s or `a`s */
.pagination-item {
display: block;
padding: 1rem;
border: 1px solid #eee;
}
.pagination-item:first-child {
margin-bottom: -1px;
}
/* Only provide a hover state for linked pagination items */
a.pagination-item:hover {
background-color: #f5f5f5;
}
@media (min-width: 30em) {
.pagination {
margin: 3rem 0;
}
.pagination-item {
float: left;
width: 50%;
}
.pagination-item:first-child {
margin-bottom: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.pagination-item:last-child {
margin-left: -1px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
}
+19
View File
@@ -0,0 +1,19 @@
.sidebar {
display: none !important;
}
.content {
margin: 0 auto;
width: 100%;
float: none;
display: initial;
}
.container {
width: 100%;
float: none;
display: initial;
padding-left: 1rem;
padding-right: 1rem;
margin: 0 auto;
}
+66
View File
@@ -0,0 +1,66 @@
.hll { background-color: #ffffcc }
/*{ background: #f0f3f3; }*/
.c { color: #999; } /* Comment */
.err { color: #AA0000; background-color: #FFAAAA } /* Error */
.k { color: #006699; } /* Keyword */
.o { color: #555555 } /* Operator */
.cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
.cp { color: #009999 } /* Comment.Preproc */
.c1 { color: #999; } /* Comment.Single */
.cs { color: #999; } /* Comment.Special */
.gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #003300; } /* Generic.Heading */
.gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
.go { color: #AAAAAA } /* Generic.Output */
.gp { color: #000099; } /* Generic.Prompt */
.gs { } /* Generic.Strong */
.gu { color: #003300; } /* Generic.Subheading */
.gt { color: #99CC66 } /* Generic.Traceback */
.kc { color: #006699; } /* Keyword.Constant */
.kd { color: #006699; } /* Keyword.Declaration */
.kn { color: #006699; } /* Keyword.Namespace */
.kp { color: #006699 } /* Keyword.Pseudo */
.kr { color: #006699; } /* Keyword.Reserved */
.kt { color: #007788; } /* Keyword.Type */
.m { color: #FF6600 } /* Literal.Number */
.s { color: #d44950 } /* Literal.String */
.na { color: #4f9fcf } /* Name.Attribute */
.nb { color: #336666 } /* Name.Builtin */
.nc { color: #00AA88; } /* Name.Class */
.no { color: #336600 } /* Name.Constant */
.nd { color: #9999FF } /* Name.Decorator */
.ni { color: #999999; } /* Name.Entity */
.ne { color: #CC0000; } /* Name.Exception */
.nf { color: #CC00FF } /* Name.Function */
.nl { color: #9999FF } /* Name.Label */
.nn { color: #00CCFF; } /* Name.Namespace */
.nt { color: #2f6f9f; } /* Name.Tag */
.nv { color: #003333 } /* Name.Variable */
.ow { color: #000000; } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #FF6600 } /* Literal.Number.Float */
.mh { color: #FF6600 } /* Literal.Number.Hex */
.mi { color: #FF6600 } /* Literal.Number.Integer */
.mo { color: #FF6600 } /* Literal.Number.Oct */
.sb { color: #CC3300 } /* Literal.String.Backtick */
.sc { color: #CC3300 } /* Literal.String.Char */
.sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
.s2 { color: #CC3300 } /* Literal.String.Double */
.se { color: #CC3300; } /* Literal.String.Escape */
.sh { color: #CC3300 } /* Literal.String.Heredoc */
.si { color: #AA0000 } /* Literal.String.Interpol */
.sx { color: #CC3300 } /* Literal.String.Other */
.sr { color: #33AAAA } /* Literal.String.Regex */
.s1 { color: #CC3300 } /* Literal.String.Single */
.ss { color: #FFCC33 } /* Literal.String.Symbol */
.bp { color: #336666 } /* Name.Builtin.Pseudo */
.vc { color: #003333 } /* Name.Variable.Class */
.vg { color: #003333 } /* Name.Variable.Global */
.vi { color: #003333 } /* Name.Variable.Instance */
.il { color: #FF6600 } /* Literal.Number.Integer.Long */
.css .o,
.css .o + .nt,
.css .nt + .nt { color: #999; }
+79
View File
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Core Documentation &middot; Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<div class="post">
<h1>Core Documentation</h1>
<ul>
<li><a href="https://github.com/google/filament/blob/master/README.md">Build Instructions</a></li>
<li><a href="https://google.github.io/filament/Filament.md.html">Filament Design</a></li>
<li><a href="https://google.github.io/filament/Materials.md.html">Materials Overview</a></li>
<li><a href="https://google.github.io/filament/Material%20Properties.pdf">Materials Ref Sheet</a></li>
</ul>
</div>
</main>
</body>
</html>
+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="https://google.github.io/filament/index.xml" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<p>
Filament is a real-time physically-based renderer written in C++. It is mobile-first, but also
multi-platform.
</p>
<iframe src="https://google.github.io/filament/webgl/parquet.html"></iframe>
<p>
We are very conscientious about keeping Filament small, fast to load, and focused on
rendering. For example, Filament does not compile materials at run time. Instead, we provide a
command line tool
(<a href="https://github.com/google/filament/tree/master/tools/matc">matc</a>)
that does this offline.
</p>
<p>
For more information, see the
<a href="documentation">core documentation</a>
and
<a href="webgl">JavaScript documentation</a>.
Check out our
<a href="https://github.com/google/filament/blob/master/README.md">README</a>
for downloads and build instructions.
</p>
</main>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Filament</title>
<link>https://google.github.io/filament/</link>
<description>Recent content on Filament</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Tue, 30 Oct 2018 13:13:14 -0700</lastBuildDate>
<atom:link href="https://google.github.io/filament/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Core Documentation</title>
<link>https://google.github.io/filament/documentation/</link>
<pubDate>Tue, 30 Oct 2018 13:13:14 -0700</pubDate>
<guid>https://google.github.io/filament/documentation/</guid>
<description> Build Instructions Filament Design Materials Overview Materials Ref Sheet </description>
</item>
<item>
<title>Web Docs / Demos</title>
<link>https://google.github.io/filament/webgl/</link>
<pubDate>Tue, 30 Oct 2018 13:13:14 -0700</pubDate>
<guid>https://google.github.io/filament/webgl/</guid>
<description> documentation JavaScript API reference Triangle Tutorial Redball Tutorial WebGL Meetup Slides (2018) demos parquet suzanne knotess </description>
</item>
</channel>
</rss>
+31
View File
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://google.github.io/filament/documentation/</loc>
<lastmod>2018-10-30T13:13:14-07:00</lastmod>
</url>
<url>
<loc>https://google.github.io/filament/webgl/</loc>
<lastmod>2018-10-30T13:13:14-07:00</lastmod>
</url>
<url>
<loc>https://google.github.io/filament/categories/</loc>
<priority>0</priority>
</url>
<url>
<loc>https://google.github.io/filament/</loc>
<lastmod>2018-10-30T13:13:14-07:00</lastmod>
<priority>0</priority>
</url>
<url>
<loc>https://google.github.io/filament/tags/</loc>
<priority>0</priority>
</url>
</urlset>
+70
View File
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tags &middot; Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="https://google.github.io/filament/tags/index.xml" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<ul class="posts">
</ul>
</main>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Tags on Filament</title>
<link>https://google.github.io/filament/tags/</link>
<description>Recent content in Tags on Filament</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<atom:link href="https://google.github.io/filament/tags/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Filament Demo</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<style>
body { margin: 0; overflow: hidden; }
canvas { touch-action: none; width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script src="tutorial_redball.js"></script>
</body>
</html>
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Filament Demo</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<style>
body { margin: 0; overflow: hidden; }
canvas { touch-action: none; width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script src="tutorial_triangle.js"></script>
</body>
</html>
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

+28
View File
File diff suppressed because one or more lines are too long
+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
<head>
<link href="//gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="Hugo 0.50" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Docs / Demos &middot; Filament</title>
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/print.css" media="print">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/poole.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/syntax.css">
<link type="text/css" rel="stylesheet" href="https://google.github.io/filament/css/hyde.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700|Tangerine:700|Inconsolata" rel="stylesheet">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/favicon.png">
<link href="" rel="alternate" type="application/rss+xml" title="Filament" />
</head>
<body class="theme-base-0d ">
<aside class="sidebar">
<div class="container sidebar-sticky">
<div class="sidebar-about">
<a href="https://google.github.io/filament/">
<div style="width:100%; height:150px">
<img src="https://google.github.io/filament/images/filament_logo_small.png" class="lightbulb" />
</div>
</a>
<p class="lead">
</p>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="https://github.com/google/filament"> GitHub Project </a>
</li><li>
<a href="/filament/documentation/"> Core Documentation </a>
</li><li>
<a href="/filament/webgl/"> Web Docs / Demos </a>
</li>
</ul>
</nav>
</div>
</aside>
<main class="content container">
<div class="post">
<h1>Web Docs / Demos</h1>
<h2 id="documentation">documentation</h2>
<ul>
<li><a href="https://google.github.io/filament/webgl/reference.html">JavaScript API reference</a></li>
<li><a href="https://google.github.io/filament/webgl/tutorial_triangle.html">Triangle Tutorial</a></li>
<li><a href="https://google.github.io/filament/webgl/tutorial_redball.html">Redball Tutorial</a></li>
<li><a href="https://prideout.net/slides/filawasm">WebGL Meetup Slides</a> (2018)</li>
</ul>
<h2 id="demos">demos</h2>
<ul>
<li><a href="https://google.github.io/filament/webgl/parquet.html">parquet</a></li>
<li><a href="https://google.github.io/filament/webgl/suzanne.html">suzanne</a></li>
<li><a href="https://prideout.net/knotess/">knotess</a></li>
</ul>
</div>
</main>
</body>
</html>
+121
View File
@@ -0,0 +1,121 @@
body {
font-family: 'Open Sans', sans-serif;
font-size: 10.5pt;
color: #222;
}
div.highlight {
padding-left: 5px;
border-left: solid 1px gray;
}
code, div.highlight pre {
font-family: 'Inconsolata', monospace;
}
.verbiage {
max-width: 800px;
padding-bottom: 20px;
border-bottom: solid 1px #ccc;
}
.verbiage a {
color: rgb(0, 137, 235);
}
a {
text-decoration: none;
color: black;
}
a:hover {
color: rgb(0, 157, 255);
}
.active {
color: rgb(0, 137, 235);
}
.disabled, .disabled:hover {
color: #ccc;
cursor: default;
}
h1 {
font-family: 'Tangerine', cursive;
font-weight: 700;
font-size: 50px;
margin: 10px 0 0 0;
}
nav {
padding: 10px;
text-align: center;
font-size: 10px;
}
nav h2 {
font-size: 12px;
margin-bottom: 0;
}
nav ul {
list-style: none;
padding: 0;
margin-top: 0;
}
nav li {
margin: 2px 0;
}
.HolyGrail,
.HolyGrail-body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.HolyGrail-nav {
order: -1;
}
@media (min-width: 500px) {
.HolyGrail-body {
flex-direction: row;
flex: 1;
}
.HolyGrail-content {
flex: 1;
}
.HolyGrail-nav {
/* 12em is the width of the columns */
flex: 0 0 12em;
}
article {
padding: 10px;
border-left: solid 1px #ccc;
}
nav {
text-align: right;
}
}
div.demo_frame {
width: 100%;
height: 200px;
border: none;
}
iframe {
width: 100%;
height: 100%;
border: none;
}
div.demo_frame > a {
position: relative;
float: right;
right: 10px;
bottom: 35px;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+124
View File
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Filament Parquet</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<link href="https://google.github.io/filament/favicon.png" rel="icon" type="image/x-icon" />
<style>
body { margin: 0; overflow: hidden; }
canvas { touch-action: none; width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script>
const iblfile = 'venetian_crossroads_2k/venetian_crossroads_2k_ibl.ktx';
const skyfile = 'venetian_crossroads_2k/venetian_crossroads_2k_skybox.ktx';
Filament.init([
'parquet.filamat',
'shader_ball.filamesh',
'floor_ao_roughness_metallic.png',
'floor_basecolor.png',
'floor_normal.png',
iblfile, skyfile
], () => {
window.VertexAttribute = Filament.VertexAttribute;
window.AttributeType = Filament.VertexBuffer$AttributeType;
window.PrimitiveType = Filament.RenderableManager$PrimitiveType;
window.IndexType = Filament.IndexBuffer$IndexType;
window.Fov = Filament.Camera$Fov;
window.LightType = Filament.LightManager$Type;
window.app = new App(document.getElementsByTagName('canvas')[0]);
});
class App {
constructor(canvas) {
this.canvas = canvas;
const engine = this.engine = Filament.Engine.create(this.canvas);
this.scene = engine.createScene();
const sunlight = Filament.EntityManager.get().create();
Filament.LightManager.Builder(LightType.SUN)
.color([0.98, 0.92, 0.89])
.intensity(100000.0)
.direction([0.6, -1.0, -0.8])
.castShadows(true)
.sunAngularRadius(1.9)
.sunHaloSize(10.0)
.sunHaloFalloff(80.0)
.build(engine, sunlight);
this.scene.addEntity(sunlight);
const indirectLight = this.ibl = engine.createIblFromKtx(iblfile);
this.scene.setIndirectLight(indirectLight);
const radians = 1.0;
indirectLight.setRotation(mat3.fromRotation(mat3.create(), radians, [0, 1, 0]))
indirectLight.setIntensity(10000);
const skybox = engine.createSkyFromKtx(skyfile);
this.scene.setSkybox(skybox);
const material = engine.createMaterial('parquet.filamat');
const matinstance = material.createInstance();
const sampler = new Filament.TextureSampler(
Filament.MinFilter.LINEAR_MIPMAP_LINEAR,
Filament.MagFilter.LINEAR,
Filament.WrapMode.CLAMP_TO_EDGE);
const ao = engine.createTextureFromPng('floor_ao_roughness_metallic.png');
const basecolor = engine.createTextureFromPng('floor_basecolor.png', {'srgb': true});
const normal = engine.createTextureFromPng('floor_normal.png');
matinstance.setTextureParameter('aoRoughnessMetallic', ao, sampler)
matinstance.setTextureParameter('baseColor', basecolor, sampler)
matinstance.setTextureParameter('normal', normal, sampler)
const mesh = engine.loadFilamesh('shader_ball.filamesh', matinstance);
this.shaderball = mesh.renderable;
this.scene.addEntity(mesh.renderable);
this.swapChain = engine.createSwapChain();
this.renderer = engine.createRenderer();
this.camera = engine.createCamera();
this.view = engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
this.resize();
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener('resize', this.resize);
window.requestAnimationFrame(this.render);
}
render() {
const radians = Date.now() / 1000;
const transform = mat4.fromRotation(mat4.create(), radians, [0, 1, 0]);
const tcm = this.engine.getTransformManager();
const inst = tcm.getInstance(this.shaderball);
tcm.setTransform(inst, transform);
inst.delete();
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 eye = [0, 1.8, 5], center = [0, 1, -1], up = [0, 1, 0];
this.camera.lookAt(eye, center, up);
const aspect = width / height;
const fov = aspect < 1 ? Fov.HORIZONTAL : Fov.VERTICAL;
this.camera.setProjectionFov(45, aspect, 1.0, 10.0, fov);
}
}
</script>
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
( 0.711359052210276, 0.618120244243888, 0.512944839711825); // L00, irradiance, pre-scaled base
(-0.097859686794440, -0.051074875645925, 0.031743366201883); // L1-1, irradiance, pre-scaled base
( 0.666450493561133, 0.592343215485817, 0.542572773129390); // L10, irradiance, pre-scaled base
(-0.352982717630514, -0.288461467537231, -0.189409915539504); // L11, irradiance, pre-scaled base
( 0.090853680635551, 0.060327316677123, 0.010716005014943); // L2-2, irradiance, pre-scaled base
(-0.215342826524111, -0.146273860675863, -0.018439571808870); // L2-1, irradiance, pre-scaled base
( 0.091524762763870, 0.090602533480792, 0.103547262056343); // L20, irradiance, pre-scaled base
(-0.263990921291501, -0.206884185001582, -0.124897034794908); // L21, irradiance, pre-scaled base
( 0.094535002755533, 0.087065672258762, 0.072778072515425); // L22, irradiance, pre-scaled base
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+141
View File
@@ -0,0 +1,141 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Filament Suzanne</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<link href="https://google.github.io/filament/favicon.png" rel="icon" type="image/x-icon" />
<style>
body { margin: 0; overflow: hidden; }
canvas { touch-action: none; width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script>
const ibl_suffix = Filament.getSupportedFormatSuffix('etc s3tc');
const albedo_suffix = Filament.getSupportedFormatSuffix('astc s3tc');
const texture_suffix = Filament.getSupportedFormatSuffix('etc');
const env = 'syferfontein_18d_clear_2k'
const ibl_url = `${env}/${env}_ibl${ibl_suffix}.ktx`;
const sky_url = `${env}/${env}_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';
Filament.init([
filamat_url,
filamesh_url,
albedo_url,
ao_url,
metallic_url,
normal_url,
roughness_url,
ibl_url,
sky_url
], () => {
window.VertexAttribute = Filament.VertexAttribute;
window.AttributeType = Filament.VertexBuffer$AttributeType;
window.PrimitiveType = Filament.RenderableManager$PrimitiveType;
window.IndexType = Filament.IndexBuffer$IndexType;
window.Fov = Filament.Camera$Fov;
window.LightType = Filament.LightManager$Type;
window.app = new App(document.getElementsByTagName('canvas')[0]);
});
class App {
constructor(canvas) {
this.canvas = canvas;
const engine = this.engine = Filament.Engine.create(this.canvas);
this.scene = engine.createScene();
const sunlight = Filament.EntityManager.get().create();
Filament.LightManager.Builder(LightType.SUN)
.color([0.98, 0.92, 0.89])
.intensity(100000.0)
.direction([0.6, -1.0, -0.8])
.castShadows(true)
.sunAngularRadius(1.9)
.sunHaloSize(10.0)
.sunHaloFalloff(80.0)
.build(engine, sunlight);
this.scene.addEntity(sunlight);
const indirectLight = this.ibl = engine.createIblFromKtx(ibl_url);
this.scene.setIndirectLight(indirectLight);
indirectLight.setIntensity(100000);
const skybox = engine.createSkyFromKtx(sky_url);
this.scene.setSkybox(skybox);
const material = engine.createMaterial(filamat_url);
const matinstance = material.createInstance();
const sampler = new Filament.TextureSampler(
Filament.MinFilter.LINEAR_MIPMAP_LINEAR,
Filament.MagFilter.LINEAR,
Filament.WrapMode.CLAMP_TO_EDGE);
const albedo = engine.createTextureFromKtx(albedo_url, {srgb: true});
const roughness = engine.createTextureFromKtx(roughness_url);
const metallic = engine.createTextureFromKtx(metallic_url);
const normal = engine.createTextureFromKtx(normal_url);
const ao = engine.createTextureFromKtx(ao_url);
matinstance.setTextureParameter('albedo', albedo, sampler)
matinstance.setTextureParameter('roughness', roughness, sampler)
matinstance.setTextureParameter('metallic', metallic, sampler)
matinstance.setTextureParameter('normal', normal, sampler)
matinstance.setTextureParameter('ao', ao, sampler)
const mesh = engine.loadFilamesh(filamesh_url, matinstance);
this.suzanne = mesh.renderable;
this.scene.addEntity(mesh.renderable);
this.swapChain = engine.createSwapChain();
this.renderer = engine.createRenderer();
this.camera = engine.createCamera();
this.view = engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
this.resize();
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener('resize', this.resize);
window.requestAnimationFrame(this.render);
}
render() {
const radians = Date.now() / 1000;
const transform = mat4.fromRotation(mat4.create(), radians, [0, 1, 0]);
const tcm = this.engine.getTransformManager();
const inst = tcm.getInstance(this.suzanne);
tcm.setTransform(inst, transform);
inst.delete();
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 eye = [0, 0, 4], center = [0, 0, 0], up = [0, 1, 0];
this.camera.lookAt(eye, center, up);
const aspect = width / height;
const fov = aspect < 1 ? Fov.HORIZONTAL : Fov.VERTICAL;
this.camera.setProjectionFov(45, aspect, 1.0, 10.0, fov);
}
}
</script>
</body>
</html>
@@ -0,0 +1,9 @@
( 0.176013464611134, 0.194675505056431, 0.244812758432428); // L00, irradiance, pre-scaled base
( 0.037389036129664, 0.085969848684091, 0.161622543785260); // L1-1, irradiance, pre-scaled base
( 0.106446206802314, 0.130159989906826, 0.138756340559124); // L10, irradiance, pre-scaled base
(-0.075680857590600, -0.092926821236852, -0.100172375035402); // L11, irradiance, pre-scaled base
(-0.052443353169061, -0.053657966271304, -0.055358128491363); // L2-2, irradiance, pre-scaled base
( 0.073950692409278, 0.075939700408394, 0.078192941420658); // L2-1, irradiance, pre-scaled base
( 0.024174147052132, 0.025507847416248, 0.024773513925025); // L20, irradiance, pre-scaled base
(-0.113657204926413, -0.118030820797029, -0.113375372525827); // L21, irradiance, pre-scaled base
( 0.033698964466954, 0.037489148083182, 0.037346830585128); // L22, irradiance, pre-scaled base
Binary file not shown.
Binary file not shown.
+103
View File
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Filament Triangle</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1">
<link href="https://google.github.io/filament/favicon.png" rel="icon" type="image/x-icon" />
<style>
body { margin: 0; overflow: hidden; }
canvas { touch-action: none; width: 100%; height: 100%; }
</style>
</head>
<body>
<canvas></canvas>
<script src="filament.js"></script>
<script src="gl-matrix-min.js"></script>
<script>
Filament.init([ 'nonlit.filamat' ], () => {
window.VertexAttribute = Filament.VertexAttribute;
window.AttributeType = Filament.VertexBuffer$AttributeType;
window.Projection = Filament.Camera$Projection;
window.app = new App(document.getElementsByTagName('canvas')[0]);
});
class App {
constructor(canvas) {
this.canvas = canvas;
const engine = this.engine = Filament.Engine.create(this.canvas);
this.scene = engine.createScene();
this.triangle = Filament.EntityManager.get().create();
this.scene.addEntity(this.triangle);
const TRIANGLE_POSITIONS = new Float32Array([
1, 0,
Math.cos(Math.PI * 2 / 3), Math.sin(Math.PI * 2 / 3),
Math.cos(Math.PI * 4 / 3), Math.sin(Math.PI * 4 / 3),
]);
const TRIANGLE_COLORS = new Uint32Array([0xffff0000, 0xff00ff00, 0xff0000ff]);
this.vb = Filament.VertexBuffer.Builder()
.vertexCount(3)
.bufferCount(2)
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, 8)
.attribute(VertexAttribute.COLOR, 1, AttributeType.UBYTE4, 0, 4)
.normalized(VertexAttribute.COLOR)
.build(engine);
this.vb.setBufferAt(engine, 0, TRIANGLE_POSITIONS);
this.vb.setBufferAt(engine, 1, TRIANGLE_COLORS);
this.ib = Filament.IndexBuffer.Builder()
.indexCount(3)
.bufferType(Filament.IndexBuffer$IndexType.USHORT)
.build(engine);
this.ib.setBuffer(engine, new Uint16Array([0, 1, 2]));
const mat = engine.createMaterial('nonlit.filamat');
const matinst = mat.getDefaultInstance();
Filament.RenderableManager.Builder(1)
.boundingBox([[ -1, -1, -1 ], [ 1, 1, 1 ]])
.material(0, matinst)
.geometry(0, Filament.RenderableManager$PrimitiveType.TRIANGLES, this.vb, this.ib)
.build(engine, this.triangle);
this.swapChain = engine.createSwapChain();
this.renderer = engine.createRenderer();
this.camera = engine.createCamera();
this.view = engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
this.resize();
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener('resize', this.resize);
window.requestAnimationFrame(this.render);
}
render() {
const radians = Date.now() / 1000;
const transform = mat4.fromRotation(mat4.create(), radians, [0, 0, 1]);
const tcm = this.engine.getTransformManager();
const inst = tcm.getInstance(this.triangle);
tcm.setTransform(inst, transform);
inst.delete();
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;
this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
}
}
</script>
</body>
</html>
+277
View File
@@ -0,0 +1,277 @@
<!DOCTYPE html>
<html lang="en"><head>
<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_redball.html"></iframe><a href="demo_redball.html">&#x1F517;</a></div>
<p>This tutorial will describe how to create the redball demo, introducing you to materials and
textures.</p>
<p>You'll need to use a couple command-line tools: <code>matc</code> and <code>cmgen</code>. You can find these in the
appropriate <a href="//github.com/google/filament/releases">Filament release</a>. You should choose the
archive that corresponds to your development machine rather than the one for web.</p>
<h2>Define plastic material</h2>
<p>The <code>matc</code> 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 <a href="">Filament Material System</a>.</p>
<p>Let's try out <code>matc</code>. Create the following file in your favorite text editor and call it
<code>plastic.mat</code>.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>material {
name : Lit,
shadingModel : lit,
parameters : [
{ type : float3, name : baseColor },
{ type : float, name : roughness },
{ type : float, name : clearCoat },
{ type : float, name : clearCoatRoughness }
],
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor.rgb = materialParams.baseColor;
material.roughness = materialParams.roughness;
material.clearCoat = materialParams.clearCoat;
material.clearCoatRoughness = materialParams.clearCoatRoughness;
}
}
</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 -O -a opengl -p mobile -o plastic.filamat plastic.mat
</pre></div>
<p>You should now have a material archive in your working directory, which we'll use later in the
tutorial.</p>
<h2>Bake environment map</h2>
<p>Next we'll use Filament's <code>cmgen</code> tool to consume a HDR environment map in latlong format, and
produce two cubemap files: a mipmapped IBL and a blurry skybox.</p>
<p>Download <a href="//github.com/google/filament/blob/master/third_party/environments/pillars_2k.hdr">pillars_2k.hdr</a>, then invoke the following command 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">=256</span> --extract-blur<span style="color: #666666">=0</span>.1 pillars_2k.hdr
</pre></div>
<p>You should now have a <code>pillars_2k</code> 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.</p>
<h2>Create HTML and JavaScript</h2>
<p>Create a text file called <code>redball.html</code> and copy over the HTML that we used in the <a href="tutorial_triangle.html">previous
tutorial</a>. Change the last script tag from <code>triangle.js</code> to <code>redball.js</code>.</p>
<p>Next, create <code>redball.js</code> with the following content.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>Filament.init([ <span style="color: #BA2121">&#39;plastic.filamat&#39;</span>, <span style="color: #BA2121">&#39;pillars_2k_ibl.ktx&#39;</span>, <span style="color: #BA2121">&#39;pillars_2k_skybox.ktx&#39;</span> ], () =&gt; {
<span style="color: #408080; font-style: italic">// Create some global aliases to enums for convenience.</span>
<span style="color: #008000">window</span>.VertexAttribute <span style="color: #666666">=</span> Filament.VertexAttribute;
<span style="color: #008000">window</span>.AttributeType <span style="color: #666666">=</span> Filament.VertexBuffer$AttributeType;
<span style="color: #008000">window</span>.PrimitiveType <span style="color: #666666">=</span> Filament.RenderableManager$PrimitiveType;
<span style="color: #008000">window</span>.IndexType <span style="color: #666666">=</span> Filament.IndexBuffer$IndexType;
<span style="color: #008000">window</span>.Fov <span style="color: #666666">=</span> Filament.Camera$Fov;
<span style="color: #008000">window</span>.LightType <span style="color: #666666">=</span> Filament.LightManager$Type;
<span style="color: #408080; font-style: italic">// Obtain the canvas DOM object and pass it to the App.</span>
<span style="color: #008000; font-weight: bold">const</span> canvas <span style="color: #666666">=</span> <span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>];
<span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> App(canvas);
} );
<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">const</span> engine <span style="color: #666666">=</span> <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">const</span> scene <span style="color: #666666">=</span> engine.createScene();
<span style="color: #408080; font-style: italic">// TODO: create material</span>
<span style="color: #408080; font-style: italic">// TODO: create sphere</span>
<span style="color: #408080; font-style: italic">// TODO: create lights</span>
<span style="color: #408080; font-style: italic">// TODO: create IBL</span>
<span style="color: #408080; font-style: italic">// TODO: create skybox</span>
<span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> engine.createSwapChain();
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> engine.createRenderer();
<span style="color: #008000; font-weight: bold">this</span>.camera <span style="color: #666666">=</span> engine.createCamera();
<span style="color: #008000; font-weight: bold">this</span>.view <span style="color: #666666">=</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(scene);
<span style="color: #008000; font-weight: bold">this</span>.resize();
<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">&quot;resize&quot;</span>, <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: #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">const</span> radians <span style="color: #666666">=</span> <span style="color: #008000">Date</span>.now() <span style="color: #666666">/</span> <span style="color: #666666">10000</span>;
vec3.rotateY(eye, eye, center, radians);
<span style="color: #008000; font-weight: bold">this</span>.camera.lookAt(eye, center, up);
<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">this</span>.camera.setProjectionFov(<span style="color: #666666">45</span>, width <span style="color: #666666">/</span> height, <span style="color: #666666">1.0</span>, <span style="color: #666666">10.0</span>, Fov.VERTICAL);
}
}
</pre></div>
<p>The above boilerplate should be familiar to you from the previous tutorial, although it loads in a
new set of assets. We also added some animation to the camera.</p>
<p>Next let's create a material instance from the package that we built at the beginning the tutorial.
Replace the <strong>create material</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> material <span style="color: #666666">=</span> engine.createMaterial(<span style="color: #BA2121">&#39;plastic.filamat&#39;</span>);
<span style="color: #008000; font-weight: bold">const</span> matinstance <span style="color: #666666">=</span> material.createInstance();
<span style="color: #008000; font-weight: bold">const</span> red <span style="color: #666666">=</span> [<span style="color: #666666">0.8</span>, <span style="color: #666666">0.0</span>, <span style="color: #666666">0.0</span>];
matinstance.setColorParameter(<span style="color: #BA2121">&quot;baseColor&quot;</span>, Filament.RgbType.sRGB, red);
matinstance.setFloatParameter(<span style="color: #BA2121">&quot;roughness&quot;</span>, <span style="color: #666666">0.5</span>);
matinstance.setFloatParameter(<span style="color: #BA2121">&quot;clearCoat&quot;</span>, <span style="color: #666666">1.0</span>);
matinstance.setFloatParameter(<span style="color: #BA2121">&quot;clearCoatRoughness&quot;</span>, <span style="color: #666666">0.3</span>);
</pre></div>
<p>The next step is to create a renderable for the sphere. To help with this, we'll use the <code>IcoSphere</code>
utility class, whose constructor takes a LOD. Its job is to subdivide an icosadedron, producing
three arrays:</p>
<ul>
<li><code>icosphere.vertices</code> Float32Array of XYZ coordinates.</li>
<li><code>icosphere.tangents</code> Uint16Array (interpreted as half-floats) encoding the surface orientation
as quaternions.</li>
<li><code>icosphere.triangles</code> Uint16Array with triangle indices.</li>
</ul>
<p>Let's go ahead use these arrays to build the vertex buffer and index buffer. Replace <strong>create
sphere</strong> 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> renderable <span style="color: #666666">=</span> Filament.EntityManager.get().create();
scene.addEntity(renderable);
<span style="color: #008000; font-weight: bold">const</span> icosphere <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Filament.IcoSphere(<span style="color: #666666">5</span>);
<span style="color: #008000; font-weight: bold">const</span> vb <span style="color: #666666">=</span> Filament.VertexBuffer.Builder()
.vertexCount(icosphere.vertices.length <span style="color: #666666">/</span> <span style="color: #666666">3</span>)
.bufferCount(<span style="color: #666666">2</span>)
.attribute(VertexAttribute.POSITION, <span style="color: #666666">0</span>, AttributeType.FLOAT3, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>)
.attribute(VertexAttribute.TANGENTS, <span style="color: #666666">1</span>, AttributeType.SHORT4, <span style="color: #666666">0</span>, <span style="color: #666666">0</span>)
.normalized(VertexAttribute.TANGENTS)
.build(engine);
<span style="color: #008000; font-weight: bold">const</span> ib <span style="color: #666666">=</span> Filament.IndexBuffer.Builder()
.indexCount(icosphere.triangles.length)
.bufferType(IndexType.USHORT)
.build(engine);
vb.setBufferAt(engine, <span style="color: #666666">0</span>, icosphere.vertices);
vb.setBufferAt(engine, <span style="color: #666666">1</span>, icosphere.tangents);
ib.setBuffer(engine, icosphere.triangles);
Filament.RenderableManager.Builder(<span style="color: #666666">1</span>)
.boundingBox([ [<span style="color: #666666">-1</span>, <span style="color: #666666">-1</span>, <span style="color: #666666">-1</span>], [<span style="color: #666666">1</span>, <span style="color: #666666">1</span>, <span style="color: #666666">1</span>] ])
.material(<span style="color: #666666">0</span>, matinstance)
.geometry(<span style="color: #666666">0</span>, PrimitiveType.TRIANGLES, vb, ib)
.build(engine, renderable);
</pre></div>
<p>At this point, the app is rendering a sphere, but it is black so it doesn't show up. To prove that
the sphere is there, you can try changing the background color to blue via <code>setClearColor</code>, like we
did in the first tutorial.</p>
<h2>Add lighting</h2>
<p>In this section we will create some directional light sources, as well as an image-based light (IBL)
defined by one of the KTX files we built at the start of the demo. First, replace the <strong>create
lights</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> sunlight <span style="color: #666666">=</span> Filament.EntityManager.get().create();
scene.addEntity(sunlight);
Filament.LightManager.Builder(LightType.SUN)
.color([<span style="color: #666666">0.98</span>, <span style="color: #666666">0.92</span>, <span style="color: #666666">0.89</span>])
.intensity(<span style="color: #666666">110000.0</span>)
.direction([<span style="color: #666666">0.6</span>, <span style="color: #666666">-1.0</span>, <span style="color: #666666">-0.8</span>])
.sunAngularRadius(<span style="color: #666666">1.9</span>)
.sunHaloSize(<span style="color: #666666">10.0</span>)
.sunHaloFalloff(<span style="color: #666666">80.0</span>)
.build(engine, sunlight);
<span style="color: #008000; font-weight: bold">const</span> backlight <span style="color: #666666">=</span> Filament.EntityManager.get().create();
scene.addEntity(backlight);
Filament.LightManager.Builder(LightType.DIRECTIONAL)
.direction([<span style="color: #666666">-1</span>, <span style="color: #666666">0</span>, <span style="color: #666666">1</span>])
.intensity(<span style="color: #666666">50000.0</span>)
.build(engine, backlight);
</pre></div>
<p>The <code>SUN</code> light source is similar to the <code>DIRECTIONAL</code> light source, but has some extra
parameters because Filament will automatically draw a disk into the skybox.</p>
<p>Next we need to create an <code>IndirectLight</code> object from the KTX IBL. One way of doing this is the
following (don't type this out, there's an easier way).</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> format <span style="color: #666666">=</span> Filament.PixelDataFormat.RGBM;
<span style="color: #008000; font-weight: bold">const</span> datatype <span style="color: #666666">=</span> Filament.PixelDataType.UBYTE;
<span style="color: #408080; font-style: italic">// Create a Texture object for the mipmapped cubemap.</span>
<span style="color: #008000; font-weight: bold">const</span> ibl_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[<span style="color: #BA2121">&#39;pillars_2k_ibl.ktx&#39;</span>]);
<span style="color: #008000; font-weight: bold">const</span> iblktx <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Filament.KtxBundle(ibl_package);
<span style="color: #008000; font-weight: bold">const</span> ibltex <span style="color: #666666">=</span> Filament.Texture.Builder()
.width(iblktx.info().pixelWidth)
.height(iblktx.info().pixelHeight)
.levels(iblktx.getNumMipLevels())
.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP)
.format(Filament.Texture$InternalFormat.RGBA8)
.rgbm(<span style="color: #008000; font-weight: bold">true</span>)
.build(engine);
<span style="color: #008000; font-weight: bold">for</span> (<span style="color: #008000; font-weight: bold">let</span> level <span style="color: #666666">=</span> <span style="color: #666666">0</span>; level <span style="color: #666666">&lt;</span> iblktx.getNumMipLevels(); <span style="color: #666666">++</span>level) {
<span style="color: #008000; font-weight: bold">const</span> uint8array <span style="color: #666666">=</span> iblktx.getCubeBlob(level).getBytes();
<span style="color: #008000; font-weight: bold">const</span> pixelbuffer <span style="color: #666666">=</span> Filament.PixelBuffer(uint8array, format, datatype);
ibltex.setImageCube(engine, level, pixelbuffer);
}
<span style="color: #408080; font-style: italic">// Parse the spherical harmonics metadata.</span>
<span style="color: #008000; font-weight: bold">const</span> shstring <span style="color: #666666">=</span> iblktx.getMetadata(<span style="color: #BA2121">&quot;sh&quot;</span>);
<span style="color: #008000; font-weight: bold">const</span> shfloats <span style="color: #666666">=</span> shstring.split(<span style="color: #BB6688">/\s/</span>, <span style="color: #666666">9</span> <span style="color: #666666">*</span> <span style="color: #666666">3</span>).map(<span style="color: #008000">parseFloat</span>);
<span style="color: #408080; font-style: italic">// Build the IBL object and insert it into the scene.</span>
<span style="color: #008000; font-weight: bold">const</span> indirectLight <span style="color: #666666">=</span> Filament.IndirectLight.Builder()
.reflections(ibltex)
.irradianceSh(<span style="color: #666666">3</span>, shfloats)
.intensity(<span style="color: #666666">50000.0</span>)
.build(engine);
scene.setIndirectLight(indirectLight);
</pre></div>
<p>Filament provides a JavaScript utility to make this simpler,
simply replace the <strong>create IBL</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> indirectLight <span style="color: #666666">=</span> engine.createIblFromKtx(<span style="color: #BA2121">&#39;pillars_2k_ibl.ktx&#39;</span>);
indirectLight.setIntensity(<span style="color: #666666">50000</span>);
scene.setIndirectLight(indirectLight);
</pre></div>
<h2>Add background</h2>
<p>At this point you can run the demo and you should see a red plastic ball against a black background.
Without a skybox, the reflections on the ball are not representative of its surroundings.
Here's one way to create a texture for the skybox:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> sky_package <span style="color: #666666">=</span> Filament.Buffer(Filament.assets[<span style="color: #BA2121">&#39;pillars_2k_skybox.ktx&#39;</span>]);
<span style="color: #008000; font-weight: bold">const</span> skyktx <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Filament.KtxBundle(sky_package);
<span style="color: #008000; font-weight: bold">const</span> skytex <span style="color: #666666">=</span> Filament.Texture.Builder()
.width(skyktx.info().pixelWidth)
.height(skyktx.info().pixelHeight)
.levels(<span style="color: #666666">1</span>)
.sampler(Filament.Texture$Sampler.SAMPLER_CUBEMAP)
.format(Filament.Texture$InternalFormat.RGBA8)
.rgbm(<span style="color: #008000; font-weight: bold">true</span>)
.build(engine);
<span style="color: #008000; font-weight: bold">const</span> uint8array <span style="color: #666666">=</span> skyktx.getCubeBlob(<span style="color: #666666">0</span>).getBytes();
<span style="color: #008000; font-weight: bold">const</span> pixelbuffer <span style="color: #666666">=</span> Filament.PixelBuffer(uint8array, format, datatype);
skytex.setImageCube(engine, <span style="color: #666666">0</span>, pixelbuffer);
</pre></div>
<p>Filament provides a Javascript utility to make this easier.
Replace <strong>create skybox</strong> with the following.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> skybox <span style="color: #666666">=</span> engine.createSkyFromKtx(<span style="color: #BA2121">&#39;pillars_2k_skybox.ktx&#39;</span>);
scene.setSkybox(skybox);
</pre></div>
<p>That's it, we now have a shiny red ball floating in an environment! The complete JavaScript
file is available <a href="tutorial_redball.js">here</a>.</p>
</body>
</html>
+103
View File
@@ -0,0 +1,103 @@
Filament.init(['plastic.filamat', 'pillars_2k/pillars_2k_ibl.ktx', 'pillars_2k/pillars_2k_skybox.ktx'], () => {
// Create some global aliases to enums for convenience.
window.VertexAttribute = Filament.VertexAttribute;
window.AttributeType = Filament.VertexBuffer$AttributeType;
window.PrimitiveType = Filament.RenderableManager$PrimitiveType;
window.IndexType = Filament.IndexBuffer$IndexType;
window.Fov = Filament.Camera$Fov;
window.LightType = Filament.LightManager$Type;
// Obtain the canvas DOM object and pass it to the App.
const canvas = document.getElementsByTagName('canvas')[0];
window.app = new App(canvas);
});
class App {
constructor(canvas) {
this.canvas = canvas;
const engine = this.engine = Filament.Engine.create(canvas);
const scene = engine.createScene();
const material = engine.createMaterial('plastic.filamat');
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);
const renderable = Filament.EntityManager.get()
.create();
scene.addEntity(renderable);
const icosphere = new Filament.IcoSphere(5);
const vb = Filament.VertexBuffer.Builder()
.vertexCount(icosphere.vertices.length / 3)
.bufferCount(2)
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT3, 0, 0)
.attribute(VertexAttribute.TANGENTS, 1, AttributeType.SHORT4, 0, 0)
.normalized(VertexAttribute.TANGENTS)
.build(engine);
const ib = Filament.IndexBuffer.Builder()
.indexCount(icosphere.triangles.length)
.bufferType(IndexType.USHORT)
.build(engine);
vb.setBufferAt(engine, 0, icosphere.vertices);
vb.setBufferAt(engine, 1, icosphere.tangents);
ib.setBuffer(engine, icosphere.triangles);
Filament.RenderableManager.Builder(1)
.boundingBox([
[-1, -1, -1],
[1, 1, 1]
])
.material(0, matinstance)
.geometry(0, PrimitiveType.TRIANGLES, vb, ib)
.build(engine, renderable);
const sunlight = Filament.EntityManager.get()
.create();
scene.addEntity(sunlight);
Filament.LightManager.Builder(LightType.SUN)
.color([0.98, 0.92, 0.89])
.intensity(110000.0)
.direction([0.6, -1.0, -0.8])
.sunAngularRadius(1.9)
.sunHaloSize(10.0)
.sunHaloFalloff(80.0)
.build(engine, sunlight);
const backlight = Filament.EntityManager.get()
.create();
scene.addEntity(backlight);
Filament.LightManager.Builder(LightType.DIRECTIONAL)
.direction([-1, 0, 1])
.intensity(50000.0)
.build(engine, backlight);
const indirectLight = engine.createIblFromKtx('pillars_2k/pillars_2k_ibl.ktx');
indirectLight.setIntensity(50000);
scene.setIndirectLight(indirectLight);
const skybox = engine.createSkyFromKtx('pillars_2k/pillars_2k_skybox.ktx');
scene.setSkybox(skybox);
this.swapChain = engine.createSwapChain();
this.renderer = engine.createRenderer();
this.camera = engine.createCamera();
this.view = engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(scene);
this.resize();
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener("resize", this.resize);
window.requestAnimationFrame(this.render);
}
render() {
const eye = [0, 0, 4],
center = [0, 0, 0],
up = [0, 1, 0];
const radians = Date.now() / 10000;
vec3.rotateY(eye, eye, center, radians);
this.camera.lookAt(eye, center, up);
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]);
this.camera.setProjectionFov(45, width / height, 1.0, 10.0, Fov.VERTICAL);
}
}
+235
View File
@@ -0,0 +1,235 @@
<!DOCTYPE html>
<html lang="en"><head>
<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_triangle.html"></iframe><a href="demo_triangle.html">&#x1F517;</a></div>
<h2>Literate programming</h2>
<p>The markdown source for this tutorial is not only used to generate this
web page, it's also used to generate the JavaScript for the above demo.
We use a small Python script for weaving (generating HTML) and tangling
(generating JS). In the code samples, you'll often see
<code>// TODO: &lt;some task&gt;</code>. These are special markers that get replaced by
subsequent code blocks.</p>
<h2>Start your project</h2>
<p>First, create a text file called <code>triangle.html</code> and fill it with the following HTML. This creates
a mobile-friendly page with a full-screen canvas.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #BC7A00">&lt;!DOCTYPE html&gt;</span>
&lt;<span style="color: #008000; font-weight: bold">html</span> <span style="color: #7D9029">lang</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;en&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">head</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">title</span>&gt;Filament Tutorial&lt;/<span style="color: #008000; font-weight: bold">title</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #7D9029">charset</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;utf-8&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">meta</span> <span style="color: #7D9029">name</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;viewport&quot;</span> <span style="color: #7D9029">content</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;width=device-width,user-scalable=no,initial-scale=1&quot;</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">style</span>&gt;
<span style="color: #008000; font-weight: bold">body</span> { <span style="color: #008000; font-weight: bold">margin</span>: <span style="color: #666666">0</span>; <span style="color: #008000; font-weight: bold">overflow</span>: <span style="color: #008000; font-weight: bold">hidden</span>; }
<span style="color: #008000; font-weight: bold">canvas</span> { touch-action: <span style="color: #008000; font-weight: bold">none</span>; <span style="color: #008000; font-weight: bold">width</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; <span style="color: #008000; font-weight: bold">height</span>: <span style="color: #666666">100</span><span style="color: #B00040">%</span>; }
&lt;/<span style="color: #008000; font-weight: bold">style</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">head</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">body</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">canvas</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">canvas</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/filament/filament.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;//unpkg.com/gl-matrix@2.8.1/dist/gl-matrix-min.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;<span style="color: #008000; font-weight: bold">script</span> <span style="color: #7D9029">src</span><span style="color: #666666">=</span><span style="color: #BA2121">&quot;triangle.js&quot;</span>&gt;&lt;/<span style="color: #008000; font-weight: bold">script</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">body</span>&gt;
&lt;/<span style="color: #008000; font-weight: bold">html</span>&gt;
</pre></div>
<p>The above HTML loads three JavaScript files:</p>
<ul>
<li><code>filament.js</code> does a couple things:
<ul>
<li>Downloads assets and compiles the Filament WASM module.</li>
<li>Contains high-level utilities, e.g. to simplify loading KTX textures from JavaScript.</li>
</ul>
</li>
<li><code>gl-matrix-min.js</code> is a small library that provides vector math functionality.</li>
<li><code>triangle.js</code> will contain your application code.</li>
</ul>
<p>Go ahead and create <code>triangle.js</code> with the following content.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">class</span> App {
constructor() {
<span style="color: #408080; font-style: italic">// TODO: create entities</span>
<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">&quot;resize&quot;</span>, <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: render scene</span>
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
resize() {
<span style="color: #408080; font-style: italic">// TODO: adjust viewport and canvas</span>
}
}
Filament.init([<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>], () =&gt; { <span style="color: #008000">window</span>.app <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> App() } );
</pre></div>
<p>The two calls to <code>bind()</code> allow us to pass instance methods as callbacks for animation and resize
events.</p>
<p><code>Filament.init()</code> consumes two things: a list of asset URLs and a callback.</p>
<p>The callback will be triggered only after all assets finish downloading and the Filament module has
become ready. In our callback, we simply instantiated the <code>App</code> object, since we'll do most of the
work in its constructor. We also set the app instance into a <code>Window</code> property to make it accessible
from the developer console.</p>
<p>Go ahead and download <a href="triangle.filamat">triangle.filamat</a> and place it in your project folder.
This is a <em>material package</em>, which is a binary file that contains shaders and other bits of data
that define a PBR material. We'll learn more about material packages in the next tutorial.</p>
<h2>Spawn a local server</h2>
<p>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:</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>python3 -m http.server <span style="color: #408080; font-style: italic"># Python 3</span>
python -m SimpleHTTPServer <span style="color: #408080; font-style: italic"># Python 2.7</span>
</pre></div>
<p>To see if this works, navigate to <a href="http://localhost:8000">http://localhost:8000</a> and check if you
can load the page without any errors appearing in the developer console.</p>
<h2>Create the Engine and Scene</h2>
<p>We now have a basic skeleton that can respond to paint and resize events. Let's start adding
Filament objects to the app. Insert the following code into the top of the app constructor.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.canvas <span style="color: #666666">=</span> <span style="color: #008000">document</span>.getElementsByTagName(<span style="color: #BA2121">&#39;canvas&#39;</span>)[<span style="color: #666666">0</span>];
<span style="color: #008000; font-weight: bold">const</span> engine <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">this</span>.engine <span style="color: #666666">=</span> Filament.Engine.create(<span style="color: #008000; font-weight: bold">this</span>.canvas);
</pre></div>
<p>The above snippet creates the <code>Engine</code> by passing it a canvas DOM object. The engine needs the
canvas in order to create a WebGL 2.0 context in its contructor.</p>
<p>The engine is a factory for many Filament entities, including <code>Scene</code>, which is a flat container of
entities. Let's go ahead and create a scene, then add a blank entity called <code>triangle</code> into the
scene.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.scene <span style="color: #666666">=</span> engine.createScene();
<span style="color: #008000; font-weight: bold">this</span>.triangle <span style="color: #666666">=</span> Filament.EntityManager.get().create();
<span style="color: #008000; font-weight: bold">this</span>.scene.addEntity(<span style="color: #008000; font-weight: bold">this</span>.triangle);
</pre></div>
<p>Filament uses an <a href="//en.wikipedia.org/wiki/Entity-component-system">Entity-Component System</a>.
The triangle entity in the above snippet does not yet have an associated component. Later in the
tutorial we will make it into a <em>renderable</em>. Renderables are entities that have associated draw
calls.</p>
<h2>Construct typed arrays</h2>
<p>Next we'll create two typed arrays: a positions array with XY coordinates for each vertex, and a
colors array with a 32-bit word for each vertex.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> TRIANGLE_POSITIONS <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Float32Array([
<span style="color: #666666">1</span>, <span style="color: #666666">0</span>,
<span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI <span style="color: #666666">*</span> <span style="color: #666666">2</span> <span style="color: #666666">/</span> <span style="color: #666666">3</span>), <span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI <span style="color: #666666">*</span> <span style="color: #666666">2</span> <span style="color: #666666">/</span> <span style="color: #666666">3</span>),
<span style="color: #008000">Math</span>.cos(<span style="color: #008000">Math</span>.PI <span style="color: #666666">*</span> <span style="color: #666666">4</span> <span style="color: #666666">/</span> <span style="color: #666666">3</span>), <span style="color: #008000">Math</span>.sin(<span style="color: #008000">Math</span>.PI <span style="color: #666666">*</span> <span style="color: #666666">4</span> <span style="color: #666666">/</span> <span style="color: #666666">3</span>),
]);
<span style="color: #008000; font-weight: bold">const</span> TRIANGLE_COLORS <span style="color: #666666">=</span> <span style="color: #008000; font-weight: bold">new</span> Uint32Array([<span style="color: #666666">0xffff0000</span>, <span style="color: #666666">0xff00ff00</span>, <span style="color: #666666">0xff0000ff</span>]);
</pre></div>
<p>Next we'll use the positions and colors buffers to create a single <code>VertexBuffer</code> object.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> VertexAttribute <span style="color: #666666">=</span> Filament.VertexAttribute;
<span style="color: #008000; font-weight: bold">const</span> AttributeType <span style="color: #666666">=</span> Filament.VertexBuffer$AttributeType;
<span style="color: #008000; font-weight: bold">this</span>.vb <span style="color: #666666">=</span> Filament.VertexBuffer.Builder()
.vertexCount(<span style="color: #666666">3</span>)
.bufferCount(<span style="color: #666666">2</span>)
.attribute(VertexAttribute.POSITION, <span style="color: #666666">0</span>, AttributeType.FLOAT2, <span style="color: #666666">0</span>, <span style="color: #666666">8</span>)
.attribute(VertexAttribute.COLOR, <span style="color: #666666">1</span>, AttributeType.UBYTE4, <span style="color: #666666">0</span>, <span style="color: #666666">4</span>)
.normalized(VertexAttribute.COLOR)
.build(engine);
<span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine, <span style="color: #666666">0</span>, TRIANGLE_POSITIONS);
<span style="color: #008000; font-weight: bold">this</span>.vb.setBufferAt(engine, <span style="color: #666666">1</span>, TRIANGLE_COLORS);
</pre></div>
<p>The above snippet first creates aliases for two enum types, then constructs the vertex buffer using
its <code>Builder</code> method. After that, it pushes two buffer objects into the appropriate slots using
<code>setBufferAt</code>.</p>
<p>In the Filament API, the above builder pattern is often used for constructing objects in lieu of
long argument lists. The daisy chain of function calls allows the client code to be somewhat
self-documenting.</p>
<p>Our app sets up two buffer slots in the vertex buffer, and each slot is associated with a single
attribute. Alternatively, we could have interleaved or concatenated these attributes into a single
buffer slot.</p>
<p>Next we'll construct an index buffer. The index buffer for our triangle is trivial: it simply holds
the integers 0,1,2.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.ib <span style="color: #666666">=</span> Filament.IndexBuffer.Builder()
.indexCount(<span style="color: #666666">3</span>)
.bufferType(Filament.IndexBuffer$IndexType.USHORT)
.build(engine);
<span style="color: #008000; font-weight: bold">this</span>.ib.setBuffer(engine, <span style="color: #008000; font-weight: bold">new</span> Uint16Array([<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, <span style="color: #666666">2</span>]));
</pre></div>
<p>Note that constructing an index buffer is similar to constructing a vertex buffer, but it only has
one buffer slot, and it can only contain two types of data (USHORT or UINT).</p>
<h2>Finish up initialization</h2>
<p>Next let's construct an actual <code>Material</code> from the material package that was downloaded (the
material is an object; the package is just a binary blob), then extract the default
<code>MaterialInstance</code> from the material object. Material instances have concrete values for their
parameters, and they can be bound to renderables. We'll learn more about material instances in the
next tutorial.</p>
<p>After extracting the material instance, we can finally create a renderable component for the
triangle by setting up a bounding box and passing in the vertex and index buffers.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">const</span> mat <span style="color: #666666">=</span> engine.createMaterial(<span style="color: #BA2121">&#39;triangle.filamat&#39;</span>);
<span style="color: #008000; font-weight: bold">const</span> matinst <span style="color: #666666">=</span> mat.getDefaultInstance();
Filament.RenderableManager.Builder(<span style="color: #666666">1</span>)
.boundingBox([[ <span style="color: #666666">-1</span>, <span style="color: #666666">-1</span>, <span style="color: #666666">-1</span> ], [ <span style="color: #666666">1</span>, <span style="color: #666666">1</span>, <span style="color: #666666">1</span> ]])
.material(<span style="color: #666666">0</span>, matinst)
.geometry(<span style="color: #666666">0</span>, Filament.RenderableManager$PrimitiveType.TRIANGLES, <span style="color: #008000; font-weight: bold">this</span>.vb, <span style="color: #008000; font-weight: bold">this</span>.ib)
.build(engine, <span style="color: #008000; font-weight: bold">this</span>.triangle);
</pre></div>
<p>Next let's wrap up the initialization routine by creating the swap chain, renderer, camera, and
view.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">this</span>.swapChain <span style="color: #666666">=</span> engine.createSwapChain();
<span style="color: #008000; font-weight: bold">this</span>.renderer <span style="color: #666666">=</span> engine.createRenderer();
<span style="color: #008000; font-weight: bold">this</span>.camera <span style="color: #666666">=</span> engine.createCamera();
<span style="color: #008000; font-weight: bold">this</span>.view <span style="color: #666666">=</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>.view.setClearColor([<span style="color: #666666">0.1</span>, <span style="color: #666666">0.2</span>, <span style="color: #666666">0.3</span>, <span style="color: #666666">1.0</span>]); <span style="color: #408080; font-style: italic">// blue-green background</span>
<span style="color: #008000; font-weight: bold">this</span>.resize(); <span style="color: #408080; font-style: italic">// adjust the initial viewport</span>
</pre></div>
<p>At this point, we're done creating all Filament entities, and the code should run without errors.
However the canvas is still blank!</p>
<h2>Render and resize handlers</h2>
<p>Recall that our App class has a skeletal render method, which the browser calls every time it needs
to repaint. Often this is 60 times a second.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>render() {
<span style="color: #408080; font-style: italic">// TODO: render scene</span>
<span style="color: #008000">window</span>.requestAnimationFrame(<span style="color: #008000; font-weight: bold">this</span>.render);
}
</pre></div>
<p>Let's flesh this out by rotating the triangle and invoking the Filament renderer. Add the following
code to the top of the render method.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic">// Rotate the triangle.</span>
<span style="color: #008000; font-weight: bold">const</span> radians <span style="color: #666666">=</span> <span style="color: #008000">Date</span>.now() <span style="color: #666666">/</span> <span style="color: #666666">1000</span>;
<span style="color: #008000; font-weight: bold">const</span> transform <span style="color: #666666">=</span> mat4.fromRotation(mat4.create(), radians, [<span style="color: #666666">0</span>, <span style="color: #666666">0</span>, <span style="color: #666666">1</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>.triangle);
tcm.setTransform(inst, transform);
inst.<span style="color: #008000; font-weight: bold">delete</span>();
<span style="color: #408080; font-style: italic">// Render the frame.</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);
</pre></div>
<p>The first half of our render method obtains the transform component of the triangle entity and uses
gl-matrix to generate a rotation matrix.</p>
<p>The second half of our render method invokes the Filament renderer on the view, and tells the
Filament engine to execute its internal command buffer. The Filament renderer can tell the app
that it wants to skip a frame, hence the <code>if</code> statement.</p>
<p>One last step. Add the following code to the resize method. This adjusts the resolution of the
rendering surface when the window size changes, taking <code>devicePixelRatio</code> into account for high-DPI
displays. It also adjusts the camera frustum accordingly.</p>
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><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> Projection <span style="color: #666666">=</span> Filament.Camera$Projection;
<span style="color: #008000; font-weight: bold">this</span>.camera.setProjection(Projection.ORTHO, <span style="color: #666666">-</span>aspect, aspect, <span style="color: #666666">-1</span>, <span style="color: #666666">1</span>, <span style="color: #666666">0</span>, <span style="color: #666666">1</span>);
</pre></div>
<p>You should now have a spinning triangle! The completed JavaScript is available
<a href="tutorial_triangle.js">here</a>. In the next tutorial, we'll take a closer look at Filament
materials and 3D rendering.</p>
</body>
</html>
+78
View File
@@ -0,0 +1,78 @@
class App {
constructor() {
this.canvas = document.getElementsByTagName('canvas')[0];
const engine = this.engine = Filament.Engine.create(this.canvas);
this.scene = engine.createScene();
this.triangle = Filament.EntityManager.get()
.create();
this.scene.addEntity(this.triangle);
const TRIANGLE_POSITIONS = new Float32Array([
1, 0,
Math.cos(Math.PI * 2 / 3), Math.sin(Math.PI * 2 / 3),
Math.cos(Math.PI * 4 / 3), Math.sin(Math.PI * 4 / 3),
]);
const TRIANGLE_COLORS = new Uint32Array([0xffff0000, 0xff00ff00, 0xff0000ff]);
const VertexAttribute = Filament.VertexAttribute;
const AttributeType = Filament.VertexBuffer$AttributeType;
this.vb = Filament.VertexBuffer.Builder()
.vertexCount(3)
.bufferCount(2)
.attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, 8)
.attribute(VertexAttribute.COLOR, 1, AttributeType.UBYTE4, 0, 4)
.normalized(VertexAttribute.COLOR)
.build(engine);
this.vb.setBufferAt(engine, 0, TRIANGLE_POSITIONS);
this.vb.setBufferAt(engine, 1, TRIANGLE_COLORS);
this.ib = Filament.IndexBuffer.Builder()
.indexCount(3)
.bufferType(Filament.IndexBuffer$IndexType.USHORT)
.build(engine);
this.ib.setBuffer(engine, new Uint16Array([0, 1, 2]));
const mat = engine.createMaterial('triangle.filamat');
const matinst = mat.getDefaultInstance();
Filament.RenderableManager.Builder(1)
.boundingBox([
[-1, -1, -1],
[1, 1, 1]
])
.material(0, matinst)
.geometry(0, Filament.RenderableManager$PrimitiveType.TRIANGLES, this.vb, this.ib)
.build(engine, this.triangle);
this.swapChain = engine.createSwapChain();
this.renderer = engine.createRenderer();
this.camera = engine.createCamera();
this.view = engine.createView();
this.view.setCamera(this.camera);
this.view.setScene(this.scene);
this.view.setClearColor([0.1, 0.2, 0.3, 1.0]); // blue-green background
this.resize(); // adjust the initial viewport
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
window.addEventListener("resize", this.resize);
window.requestAnimationFrame(this.render);
}
render() {
// Rotate the triangle.
const radians = Date.now() / 1000;
const transform = mat4.fromRotation(mat4.create(), radians, [0, 0, 1]);
const tcm = this.engine.getTransformManager();
const inst = tcm.getInstance(this.triangle);
tcm.setTransform(inst, transform);
inst.delete();
// Render the frame.
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 Projection = Filament.Camera$Projection;
this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
}
}
Filament.init(['triangle.filamat'], () => {
window.app = new App()
});
+9
View File
@@ -0,0 +1,9 @@
( 0.199599473290091, 0.197587181694140, 0.208682252219075); // L00, irradiance, pre-scaled base
( 0.089495502705593, 0.126984777315514, 0.187462491049106); // L1-1, irradiance, pre-scaled base
( 0.092171090498250, 0.102496785921704, 0.105307785716618); // L10, irradiance, pre-scaled base
(-0.032283343382116, -0.053886007247673, -0.066118108745634); // L11, irradiance, pre-scaled base
(-0.073408100483914, -0.080873118996811, -0.078844649300054); // L2-2, irradiance, pre-scaled base
( 0.062074830012856, 0.085152602505844, 0.100914239211979); // L2-1, irradiance, pre-scaled base
( 0.007634819958563, 0.005643621723757, -0.000848833137690); // L20, irradiance, pre-scaled base
(-0.102654258144892, -0.102815468288420, -0.093088103336565); // L21, irradiance, pre-scaled base
(-0.022778021491272, -0.028188258289506, -0.037725645536498); // L22, irradiance, pre-scaled base
Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 13 KiB