jme3_shaders.html 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <meta name="generator" content="Asciidoctor 1.5.4">
  8. <title>JME3 and Shaders</title>
  9. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
  10. <style>
  11. /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
  12. /* Remove comment around @import statement below when using as a custom stylesheet */
  13. /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
  14. article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
  15. audio,canvas,video{display:inline-block}
  16. audio:not([controls]){display:none;height:0}
  17. [hidden],template{display:none}
  18. script{display:none!important}
  19. html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
  20. body{margin:0}
  21. a{background:transparent}
  22. a:focus{outline:thin dotted}
  23. a:active,a:hover{outline:0}
  24. h1{font-size:2em;margin:.67em 0}
  25. abbr[title]{border-bottom:1px dotted}
  26. b,strong{font-weight:bold}
  27. dfn{font-style:italic}
  28. hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
  29. mark{background:#ff0;color:#000}
  30. code,kbd,pre,samp{font-family:monospace;font-size:1em}
  31. pre{white-space:pre-wrap}
  32. q{quotes:"\201C" "\201D" "\2018" "\2019"}
  33. small{font-size:80%}
  34. sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
  35. sup{top:-.5em}
  36. sub{bottom:-.25em}
  37. img{border:0}
  38. svg:not(:root){overflow:hidden}
  39. figure{margin:0}
  40. fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
  41. legend{border:0;padding:0}
  42. button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
  43. button,input{line-height:normal}
  44. button,select{text-transform:none}
  45. button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
  46. button[disabled],html input[disabled]{cursor:default}
  47. input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
  48. input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
  49. input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
  50. button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
  51. textarea{overflow:auto;vertical-align:top}
  52. table{border-collapse:collapse;border-spacing:0}
  53. *,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
  54. html,body{font-size:100%}
  55. body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
  56. a:hover{cursor:pointer}
  57. img,object,embed{max-width:100%;height:auto}
  58. object,embed{height:100%}
  59. img{-ms-interpolation-mode:bicubic}
  60. .left{float:left!important}
  61. .right{float:right!important}
  62. .text-left{text-align:left!important}
  63. .text-right{text-align:right!important}
  64. .text-center{text-align:center!important}
  65. .text-justify{text-align:justify!important}
  66. .hide{display:none}
  67. body{-webkit-font-smoothing:antialiased}
  68. img,object,svg{display:inline-block;vertical-align:middle}
  69. textarea{height:auto;min-height:50px}
  70. select{width:100%}
  71. .center{margin-left:auto;margin-right:auto}
  72. .spread{width:100%}
  73. p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
  74. .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
  75. div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
  76. a{color:#2156a5;text-decoration:underline;line-height:inherit}
  77. a:hover,a:focus{color:#1d4b8f}
  78. a img{border:none}
  79. p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
  80. p aside{font-size:.875em;line-height:1.35;font-style:italic}
  81. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
  82. h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
  83. h1{font-size:2.125em}
  84. h2{font-size:1.6875em}
  85. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
  86. h4,h5{font-size:1.125em}
  87. h6{font-size:1em}
  88. hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
  89. em,i{font-style:italic;line-height:inherit}
  90. strong,b{font-weight:bold;line-height:inherit}
  91. small{font-size:60%;line-height:inherit}
  92. code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
  93. ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
  94. ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
  95. ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
  96. ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
  97. ul.square{list-style-type:square}
  98. ul.circle{list-style-type:circle}
  99. ul.disc{list-style-type:disc}
  100. ul.no-bullet{list-style:none}
  101. ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
  102. dl dt{margin-bottom:.3125em;font-weight:bold}
  103. dl dd{margin-bottom:1.25em}
  104. abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
  105. abbr{text-transform:none}
  106. blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
  107. blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
  108. blockquote cite:before{content:"\2014 \0020"}
  109. blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
  110. blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
  111. @media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
  112. h1{font-size:2.75em}
  113. h2{font-size:2.3125em}
  114. h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
  115. h4{font-size:1.4375em}}
  116. table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
  117. table thead,table tfoot{background:#f7f8f7;font-weight:bold}
  118. table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
  119. table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
  120. table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
  121. table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
  122. body{tab-size:4}
  123. h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
  124. h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
  125. .clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
  126. .clearfix:after,.float-group:after{clear:both}
  127. *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
  128. pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
  129. .keyseq{color:rgba(51,51,51,.8)}
  130. kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
  131. .keyseq kbd:first-child{margin-left:0}
  132. .keyseq kbd:last-child{margin-right:0}
  133. .menuseq,.menu{color:rgba(0,0,0,.8)}
  134. b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
  135. b.button:before{content:"[";padding:0 3px 0 2px}
  136. b.button:after{content:"]";padding:0 2px 0 3px}
  137. p a>code:hover{color:rgba(0,0,0,.9)}
  138. #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
  139. #header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
  140. #header:after,#content:after,#footnotes:after,#footer:after{clear:both}
  141. #content{margin-top:1.25em}
  142. #content:before{content:none}
  143. #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
  144. #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
  145. #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
  146. #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
  147. #header .details span:first-child{margin-left:-.125em}
  148. #header .details span.email a{color:rgba(0,0,0,.85)}
  149. #header .details br{display:none}
  150. #header .details br+span:before{content:"\00a0\2013\00a0"}
  151. #header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
  152. #header .details br+span#revremark:before{content:"\00a0|\00a0"}
  153. #header #revnumber{text-transform:capitalize}
  154. #header #revnumber:after{content:"\00a0"}
  155. #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
  156. #toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
  157. #toc>ul{margin-left:.125em}
  158. #toc ul.sectlevel0>li>a{font-style:italic}
  159. #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
  160. #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
  161. #toc li{line-height:1.3334;margin-top:.3334em}
  162. #toc a{text-decoration:none}
  163. #toc a:active{text-decoration:underline}
  164. #toctitle{color:#7a2518;font-size:1.2em}
  165. @media only screen and (min-width:768px){#toctitle{font-size:1.375em}
  166. body.toc2{padding-left:15em;padding-right:0}
  167. #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
  168. #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
  169. #toc.toc2>ul{font-size:.9em;margin-bottom:0}
  170. #toc.toc2 ul ul{margin-left:0;padding-left:1em}
  171. #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
  172. body.toc2.toc-right{padding-left:0;padding-right:15em}
  173. body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
  174. @media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
  175. #toc.toc2{width:20em}
  176. #toc.toc2 #toctitle{font-size:1.375em}
  177. #toc.toc2>ul{font-size:.95em}
  178. #toc.toc2 ul ul{padding-left:1.25em}
  179. body.toc2.toc-right{padding-left:0;padding-right:20em}}
  180. #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  181. #content #toc>:first-child{margin-top:0}
  182. #content #toc>:last-child{margin-bottom:0}
  183. #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
  184. #footer-text{color:rgba(255,255,255,.8);line-height:1.44}
  185. .sect1{padding-bottom:.625em}
  186. @media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
  187. .sect1+.sect1{border-top:1px solid #efefed}
  188. #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
  189. #content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
  190. #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
  191. #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
  192. #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
  193. .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
  194. .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
  195. table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
  196. .paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
  197. table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
  198. .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
  199. .admonitionblock>table td.icon{text-align:center;width:80px}
  200. .admonitionblock>table td.icon img{max-width:none}
  201. .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
  202. .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
  203. .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
  204. .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
  205. .exampleblock>.content>:first-child{margin-top:0}
  206. .exampleblock>.content>:last-child{margin-bottom:0}
  207. .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
  208. .sidebarblock>:first-child{margin-top:0}
  209. .sidebarblock>:last-child{margin-bottom:0}
  210. .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
  211. .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
  212. .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
  213. .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
  214. .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
  215. .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
  216. @media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
  217. @media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
  218. .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
  219. .listingblock pre.highlightjs{padding:0}
  220. .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
  221. .listingblock pre.prettyprint{border-width:0}
  222. .listingblock>.content{position:relative}
  223. .listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
  224. .listingblock:hover code[data-lang]:before{display:block}
  225. .listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
  226. .listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
  227. table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
  228. table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
  229. table.pyhltable td.code{padding-left:.75em;padding-right:0}
  230. pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
  231. pre.pygments .lineno{display:inline-block;margin-right:.25em}
  232. table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
  233. .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
  234. .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
  235. .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
  236. .quoteblock blockquote{margin:0;padding:0;border:0}
  237. .quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
  238. .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
  239. .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
  240. .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
  241. .quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
  242. .quoteblock .quoteblock blockquote:before{display:none}
  243. .verseblock{margin:0 1em 1.25em 1em}
  244. .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
  245. .verseblock pre strong{font-weight:400}
  246. .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
  247. .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
  248. .quoteblock .attribution br,.verseblock .attribution br{display:none}
  249. .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
  250. .quoteblock.abstract{margin:0 0 1.25em 0;display:block}
  251. .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
  252. .quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
  253. table.tableblock{max-width:100%;border-collapse:separate}
  254. table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
  255. table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
  256. table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
  257. table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
  258. table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
  259. table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
  260. table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
  261. table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
  262. table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
  263. table.frame-all{border-width:1px}
  264. table.frame-sides{border-width:0 1px}
  265. table.frame-topbot{border-width:1px 0}
  266. th.halign-left,td.halign-left{text-align:left}
  267. th.halign-right,td.halign-right{text-align:right}
  268. th.halign-center,td.halign-center{text-align:center}
  269. th.valign-top,td.valign-top{vertical-align:top}
  270. th.valign-bottom,td.valign-bottom{vertical-align:bottom}
  271. th.valign-middle,td.valign-middle{vertical-align:middle}
  272. table thead th,table tfoot th{font-weight:bold}
  273. tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
  274. tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
  275. p.tableblock>code:only-child{background:none;padding:0}
  276. p.tableblock{font-size:1em}
  277. td>div.verse{white-space:pre}
  278. ol{margin-left:1.75em}
  279. ul li ol{margin-left:1.5em}
  280. dl dd{margin-left:1.125em}
  281. dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
  282. ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
  283. ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
  284. ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
  285. ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
  286. ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
  287. ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
  288. ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
  289. ul.inline>li>*{display:block}
  290. .unstyled dl dt{font-weight:400;font-style:normal}
  291. ol.arabic{list-style-type:decimal}
  292. ol.decimal{list-style-type:decimal-leading-zero}
  293. ol.loweralpha{list-style-type:lower-alpha}
  294. ol.upperalpha{list-style-type:upper-alpha}
  295. ol.lowerroman{list-style-type:lower-roman}
  296. ol.upperroman{list-style-type:upper-roman}
  297. ol.lowergreek{list-style-type:lower-greek}
  298. .hdlist>table,.colist>table{border:0;background:none}
  299. .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
  300. td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
  301. td.hdlist1{font-weight:bold;padding-bottom:1.25em}
  302. .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
  303. .colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
  304. .colist>table tr>td:last-of-type{padding:.25em 0}
  305. .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
  306. .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
  307. .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
  308. .imageblock>.title{margin-bottom:0}
  309. .imageblock.thumb,.imageblock.th{border-width:6px}
  310. .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
  311. .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
  312. .image.left{margin-right:.625em}
  313. .image.right{margin-left:.625em}
  314. a.image{text-decoration:none;display:inline-block}
  315. a.image object{pointer-events:none}
  316. sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
  317. sup.footnote a,sup.footnoteref a{text-decoration:none}
  318. sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
  319. #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
  320. #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
  321. #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
  322. #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
  323. #footnotes .footnote:last-of-type{margin-bottom:0}
  324. #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
  325. .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
  326. .gist .file-data>table td.line-data{width:99%}
  327. div.unbreakable{page-break-inside:avoid}
  328. .big{font-size:larger}
  329. .small{font-size:smaller}
  330. .underline{text-decoration:underline}
  331. .overline{text-decoration:overline}
  332. .line-through{text-decoration:line-through}
  333. .aqua{color:#00bfbf}
  334. .aqua-background{background-color:#00fafa}
  335. .black{color:#000}
  336. .black-background{background-color:#000}
  337. .blue{color:#0000bf}
  338. .blue-background{background-color:#0000fa}
  339. .fuchsia{color:#bf00bf}
  340. .fuchsia-background{background-color:#fa00fa}
  341. .gray{color:#606060}
  342. .gray-background{background-color:#7d7d7d}
  343. .green{color:#006000}
  344. .green-background{background-color:#007d00}
  345. .lime{color:#00bf00}
  346. .lime-background{background-color:#00fa00}
  347. .maroon{color:#600000}
  348. .maroon-background{background-color:#7d0000}
  349. .navy{color:#000060}
  350. .navy-background{background-color:#00007d}
  351. .olive{color:#606000}
  352. .olive-background{background-color:#7d7d00}
  353. .purple{color:#600060}
  354. .purple-background{background-color:#7d007d}
  355. .red{color:#bf0000}
  356. .red-background{background-color:#fa0000}
  357. .silver{color:#909090}
  358. .silver-background{background-color:#bcbcbc}
  359. .teal{color:#006060}
  360. .teal-background{background-color:#007d7d}
  361. .white{color:#bfbfbf}
  362. .white-background{background-color:#fafafa}
  363. .yellow{color:#bfbf00}
  364. .yellow-background{background-color:#fafa00}
  365. span.icon>.fa{cursor:default}
  366. .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
  367. .admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
  368. .admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
  369. .admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
  370. .admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
  371. .admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
  372. .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
  373. .conum[data-value] *{color:#fff!important}
  374. .conum[data-value]+b{display:none}
  375. .conum[data-value]:after{content:attr(data-value)}
  376. pre .conum[data-value]{position:relative;top:-.125em}
  377. b.conum *{color:inherit!important}
  378. .conum:not([data-value]):empty{display:none}
  379. dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
  380. h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
  381. p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
  382. p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
  383. p{margin-bottom:1.25rem}
  384. .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
  385. .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
  386. .print-only{display:none!important}
  387. @media print{@page{margin:1.25cm .75cm}
  388. *{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
  389. a{color:inherit!important;text-decoration:underline!important}
  390. a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
  391. a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
  392. abbr[title]:after{content:" (" attr(title) ")"}
  393. pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
  394. thead{display:table-header-group}
  395. svg{max-width:100%}
  396. p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
  397. h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
  398. #toc,.sidebarblock,.exampleblock>.content{background:none!important}
  399. #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
  400. .sect1{padding-bottom:0!important}
  401. .sect1+.sect1{border:0!important}
  402. #header>h1:first-child{margin-top:1.25rem}
  403. body.book #header{text-align:center}
  404. body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
  405. body.book #header .details{border:0!important;display:block;padding:0!important}
  406. body.book #header .details span:first-child{margin-left:0!important}
  407. body.book #header .details br{display:block}
  408. body.book #header .details br+span:before{content:none!important}
  409. body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
  410. body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
  411. .listingblock code[data-lang]:before{display:block}
  412. #footer{background:none!important;padding:0 .9375em}
  413. #footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
  414. .hide-on-print{display:none!important}
  415. .print-only{display:block!important}
  416. .hide-for-print{display:none!important}
  417. .show-for-print{display:inherit!important}}
  418. </style>
  419. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  420. <style>
  421. /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
  422. /*pre.CodeRay {background-color:#f7f7f8;}*/
  423. .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
  424. .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
  425. .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
  426. table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
  427. table.CodeRay td{vertical-align: top;line-height:1.45}
  428. table.CodeRay td.line-numbers{text-align:right}
  429. table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
  430. table.CodeRay td.code{padding:0 0 0 .5em}
  431. table.CodeRay td.code>pre{padding:0}
  432. .CodeRay .debug{color:#fff !important;background:#000080 !important}
  433. .CodeRay .annotation{color:#007}
  434. .CodeRay .attribute-name{color:#000080}
  435. .CodeRay .attribute-value{color:#700}
  436. .CodeRay .binary{color:#509}
  437. .CodeRay .comment{color:#998;font-style:italic}
  438. .CodeRay .char{color:#04d}
  439. .CodeRay .char .content{color:#04d}
  440. .CodeRay .char .delimiter{color:#039}
  441. .CodeRay .class{color:#458;font-weight:bold}
  442. .CodeRay .complex{color:#a08}
  443. .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
  444. .CodeRay .color{color:#099}
  445. .CodeRay .class-variable{color:#369}
  446. .CodeRay .decorator{color:#b0b}
  447. .CodeRay .definition{color:#099}
  448. .CodeRay .delimiter{color:#000}
  449. .CodeRay .doc{color:#970}
  450. .CodeRay .doctype{color:#34b}
  451. .CodeRay .doc-string{color:#d42}
  452. .CodeRay .escape{color:#666}
  453. .CodeRay .entity{color:#800}
  454. .CodeRay .error{color:#808}
  455. .CodeRay .exception{color:inherit}
  456. .CodeRay .filename{color:#099}
  457. .CodeRay .function{color:#900;font-weight:bold}
  458. .CodeRay .global-variable{color:#008080}
  459. .CodeRay .hex{color:#058}
  460. .CodeRay .integer,.CodeRay .float{color:#099}
  461. .CodeRay .include{color:#555}
  462. .CodeRay .inline{color:#000}
  463. .CodeRay .inline .inline{background:#ccc}
  464. .CodeRay .inline .inline .inline{background:#bbb}
  465. .CodeRay .inline .inline-delimiter{color:#d14}
  466. .CodeRay .inline-delimiter{color:#d14}
  467. .CodeRay .important{color:#555;font-weight:bold}
  468. .CodeRay .interpreted{color:#b2b}
  469. .CodeRay .instance-variable{color:#008080}
  470. .CodeRay .label{color:#970}
  471. .CodeRay .local-variable{color:#963}
  472. .CodeRay .octal{color:#40e}
  473. .CodeRay .predefined{color:#369}
  474. .CodeRay .preprocessor{color:#579}
  475. .CodeRay .pseudo-class{color:#555}
  476. .CodeRay .directive{font-weight:bold}
  477. .CodeRay .type{font-weight:bold}
  478. .CodeRay .predefined-type{color:inherit}
  479. .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
  480. .CodeRay .key{color:#808}
  481. .CodeRay .key .delimiter{color:#606}
  482. .CodeRay .key .char{color:#80f}
  483. .CodeRay .value{color:#088}
  484. .CodeRay .regexp .delimiter{color:#808}
  485. .CodeRay .regexp .content{color:#808}
  486. .CodeRay .regexp .modifier{color:#808}
  487. .CodeRay .regexp .char{color:#d14}
  488. .CodeRay .regexp .function{color:#404;font-weight:bold}
  489. .CodeRay .string{color:#d20}
  490. .CodeRay .string .string .string{background:#ffd0d0}
  491. .CodeRay .string .content{color:#d14}
  492. .CodeRay .string .char{color:#d14}
  493. .CodeRay .string .delimiter{color:#d14}
  494. .CodeRay .shell{color:#d14}
  495. .CodeRay .shell .delimiter{color:#d14}
  496. .CodeRay .symbol{color:#990073}
  497. .CodeRay .symbol .content{color:#a60}
  498. .CodeRay .symbol .delimiter{color:#630}
  499. .CodeRay .tag{color:#008080}
  500. .CodeRay .tag-special{color:#d70}
  501. .CodeRay .variable{color:#036}
  502. .CodeRay .insert{background:#afa}
  503. .CodeRay .delete{background:#faa}
  504. .CodeRay .change{color:#aaf;background:#007}
  505. .CodeRay .head{color:#f8f;background:#505}
  506. .CodeRay .insert .insert{color:#080}
  507. .CodeRay .delete .delete{color:#800}
  508. .CodeRay .change .change{color:#66f}
  509. .CodeRay .head .head{color:#f4f}
  510. </style>
  511. </head>
  512. <body class="article toc2 toc-left">
  513. <div id="header">
  514. <h1>JME3 and Shaders</h1>
  515. <div class="details">
  516. <span id="author" class="author"></span><br>
  517. <span id="revnumber">version ,</span>
  518. <span id="revdate">2016/03/17 20:48</span>
  519. </div>
  520. <div id="toc" class="toc2">
  521. <div id="toctitle">Table of Contents</div>
  522. <ul class="sectlevel0">
  523. <li><a href="#shaders-basics">Shaders Basics</a>
  524. <ul class="sectlevel2">
  525. <li><a href="#how-does-it-work">How Does it work?</a></li>
  526. <li><a href="#variables-scope">Variables scope</a></li>
  527. <li><a href="#spaces-and-matrices">Spaces and Matrices</a></li>
  528. <li><a href="#simple-example-rendering-a-solid-color-on-an-object">Simple example : rendering a solid color on an object</a></li>
  529. </ul>
  530. </li>
  531. <li><a href="#how-to-use-shaders-in-jme3">How to use shaders in JME3</a>
  532. <ul class="sectlevel2">
  533. <li><a href="#jme3-global-uniforms">JME3 Global uniforms</a></li>
  534. <li><a href="#jme3-lighting-global-uniforms">JME3 Lighting Global uniforms</a></li>
  535. <li><a href="#jme3-attributes">JME3 attributes</a></li>
  536. <li><a href="#user-s-uniforms">User&#8217;s uniforms</a></li>
  537. <li><a href="#example-adding-color-keying-to-the-lighting-j3md-material-definition">Example: Adding Color Keying to the Lighting.j3md Material Definition</a></li>
  538. <li><a href="#step-by-step">Step by step</a></li>
  539. <li><a href="#jme3-and-opengl-3-4-compatibility">JME3 and OpenGL 3 &amp; 4 compatibility</a></li>
  540. <li><a href="#useful-links">Useful links</a></li>
  541. </ul>
  542. </li>
  543. </ul>
  544. </div>
  545. </div>
  546. <div id="content">
  547. <div id="preamble">
  548. <div class="sectionbody">
  549. <div class="paragraph">
  550. <p>+</p>
  551. </div>
  552. </div>
  553. </div>
  554. <h1 id="shaders-basics" class="sect0">Shaders Basics</h1>
  555. <div class="paragraph">
  556. <p>Shaders are sets of instructions that are executed on the GPU. They are used to take advantage of hardware acceleration available on the GPU for rendering purposes.+</p>
  557. </div>
  558. <div class="paragraph">
  559. <p>This paper only covers Vertex and Fragment shaders because they are the only ones supported by JME3 for the moment. But be aware that there are some other types of shaders (geometry, tessellation,…).+</p>
  560. </div>
  561. <div class="paragraph">
  562. <p>There are multiple frequently used languages that you may encounter to code shaders but as JME3 is based on OpenGL, shaders in JME use GLSL and any example in this paper will be written in GLSL.+</p>
  563. </div>
  564. <div class="paragraph">
  565. <p>+</p>
  566. </div>
  567. <div class="sect2">
  568. <h3 id="how-does-it-work">How Does it work?</h3>
  569. <div class="paragraph">
  570. <p>To keep it Simple: The Vertex shader is executed once for each vertex in the view, then the Fragment shader (also called the Pixel shader) is executed once for each pixel on the screen.+</p>
  571. </div>
  572. <div class="paragraph">
  573. <p>The main purpose of the Vertex shader is to compute the screen coordinate of a vertex (where this vertex will be displayed on screen) while the main purpose of the Fragment shader is to compute the color of a pixel.+</p>
  574. </div>
  575. <div class="paragraph">
  576. <p>This is a very simplified graphic to describe the call stack:<br></p>
  577. </div>
  578. <div class="paragraph">
  579. <p><span class="image"><img src="../../jme3/advanced/jme3andshaders.png" alt="jme3andshaders.png" height=""></span>+</p>
  580. </div>
  581. <div class="paragraph">
  582. <p>The main program sends mesh data to the vertex shader (vertex position in object space, normals, tangents, etc..). The vertex shader computes the screen position of the vertex and sends it to the Fragment shader. The fragment shader computes the color, and the result is displayed on screen or in a texture.</p>
  583. </div>
  584. <div class="paragraph">
  585. <p>+</p>
  586. </div>
  587. </div>
  588. <div class="sect2">
  589. <h3 id="variables-scope">Variables scope</h3>
  590. <div class="paragraph">
  591. <p>There are different types of scope for variables in a shader :</p>
  592. </div>
  593. <div class="ulist">
  594. <ul>
  595. <li>
  596. <p>uniform : User defined variables that are passed by the main program to the vertex and fragment shader, these variables are global for a given execution of a shader.</p>
  597. </li>
  598. <li>
  599. <p>attribute : Per-vertex variables passed by the engine to the shader, like position, normal, etc (Mesh data in the graphic)</p>
  600. </li>
  601. <li>
  602. <p>varying : Variables passed from the vertex shader to the fragment shader.</p>
  603. </li>
  604. </ul>
  605. </div>
  606. <div class="paragraph">
  607. <p>There is a large panel of variable types to be used, for more information about it I recommend reading the GLSL specification <a href="http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf">here</a>.+</p>
  608. </div>
  609. <div class="paragraph">
  610. <p>+</p>
  611. </div>
  612. </div>
  613. <div class="sect2">
  614. <h3 id="spaces-and-matrices">Spaces and Matrices</h3>
  615. <div class="paragraph">
  616. <p>To understand the coming example you must know about the different spaces in 3D computer graphics, and the matrices used to translate coordinate from one space to another.+</p>
  617. </div>
  618. <div class="paragraph">
  619. <p><span class="image"><img src="../../jme3/advanced/jme3andshaders-1.png" alt="jme3andshaders-1.png" height=""></span>+</p>
  620. </div>
  621. <div class="paragraph">
  622. <p>The engine passes the object space coordinates to the vertex shader. We need to compute its position in projection space. To do that we transform the object space position by the WorldViewProjectionMatrix which is a combination of the World, View, Projection matrices (who would have guessed?).+</p>
  623. </div>
  624. <div class="paragraph">
  625. <p>+</p>
  626. </div>
  627. </div>
  628. <div class="sect2">
  629. <h3 id="simple-example-rendering-a-solid-color-on-an-object">Simple example : rendering a solid color on an object</h3>
  630. <div class="paragraph">
  631. <p>Here is the simplest application to shaders, rendering a solid color.+</p>
  632. </div>
  633. <div class="paragraph">
  634. <p>Vertex Shader :<br></p>
  635. </div>
  636. <div class="listingblock">
  637. <div class="content">
  638. <pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//the global uniform World view projection matrix</span>
  639. <span class="comment">//(more on global uniforms below)</span>
  640. uniform mat4 g_WorldViewProjectionMatrix;
  641. <span class="comment">//The attribute inPosition is the Object space position of the vertex</span>
  642. attribute vec3 inPosition;
  643. <span class="type">void</span> main(){
  644. <span class="comment">//Transformation of the object space coordinate to projection space</span>
  645. <span class="comment">//coordinates.</span>
  646. <span class="comment">//- gl_Position is the standard GLSL variable holding projection space</span>
  647. <span class="comment">//position. It must be filled in the vertex shader</span>
  648. <span class="comment">//- To convert position we multiply the worldViewProjectionMatrix by</span>
  649. <span class="comment">//by the position vector.</span>
  650. <span class="comment">//The multiplication must be done in this order.</span>
  651. gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, <span class="float">1.0</span>);
  652. }</code></pre>
  653. </div>
  654. </div>
  655. <div class="paragraph">
  656. <p>Fragment Shader :<br></p>
  657. </div>
  658. <div class="listingblock">
  659. <div class="content">
  660. <pre class="CodeRay highlight"><code data-lang="java"><span class="type">void</span> main(){
  661. <span class="comment">//returning the color of the pixel (here solid blue)</span>
  662. <span class="comment">//- gl_FragColor is the standard GLSL variable that holds the pixel</span>
  663. <span class="comment">//color. It must be filled in the Fragment Shader.</span>
  664. gl_FragColor = vec4(<span class="float">0.0</span>, <span class="float">0.0</span>, <span class="float">1.0</span>, <span class="float">1.0</span>);
  665. }</code></pre>
  666. </div>
  667. </div>
  668. <div class="paragraph">
  669. <p>For example applying this shader to a sphere would render a solid blue sphere on screen.+</p>
  670. </div>
  671. <div class="paragraph">
  672. <p>+</p>
  673. </div>
  674. </div>
  675. <h1 id="how-to-use-shaders-in-jme3" class="sect0">How to use shaders in JME3</h1>
  676. <div class="paragraph">
  677. <p>You probably heard that JME3 is “shader oriented”, but what does that mean?+</p>
  678. </div>
  679. <div class="paragraph">
  680. <p>Usually to use shaders you must create what is called a program. This program specify the vertex shader and the fragment shader to use.+</p>
  681. </div>
  682. <div class="paragraph">
  683. <p>JME3 encloses this in the material system. Every material in JME3 uses shaders.+</p>
  684. </div>
  685. <div class="paragraph">
  686. <p>For example let’s have a look at the SolidColor.j3md file :<br></p>
  687. </div>
  688. <div class="listingblock">
  689. <div class="content">
  690. <pre class="CodeRay highlight"><code data-lang="java">MaterialDef Solid <span class="predefined-type">Color</span> {
  691. <span class="comment">//This is the complete list of user defined uniforms to be used in the</span>
  692. <span class="comment">//shaders</span>
  693. MaterialParameters {
  694. Vector4 <span class="predefined-type">Color</span>
  695. }
  696. Technique {
  697. <span class="comment">//This is where the vertex and fragment shader files are</span>
  698. <span class="comment">//specified</span>
  699. VertexShader GLSL100: Common/MatDefs/Misc/SolidColor.vert
  700. FragmentShader GLSL100: Common/MatDefs/Misc/SolidColor.frag
  701. <span class="comment">//This is where you specify which global uniform you need for your</span>
  702. <span class="comment">//shaders</span>
  703. WorldParameters {
  704. WorldViewProjectionMatrix
  705. }
  706. }
  707. Technique FixedFunc {
  708. }
  709. }</code></pre>
  710. </div>
  711. </div>
  712. <div class="paragraph">
  713. <p>For more information on JME3 material system, i suggest you read this <a href="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/jmonkeyengine3-material-system-full-explanation">topic</a>.+</p>
  714. </div>
  715. <div class="paragraph">
  716. <p>+</p>
  717. </div>
  718. <div class="sect2">
  719. <h3 id="jme3-global-uniforms">JME3 Global uniforms</h3>
  720. <div class="paragraph">
  721. <p>JME3 can expose pre-computed global uniforms to your shaders. You must specify the one that are required for your shader in the WorldParameters section of the material definition file (.j3md).+</p>
  722. </div>
  723. <div class="paragraph">
  724. <p>Note that in the shader the uniform names will be prefixed by a “g_”.+</p>
  725. </div>
  726. <div class="paragraph">
  727. <p>In the example above, WorldViewProjectionMatrix is declared as uniform mat4 g_WorldViewProjectionMatrix in the shader.+</p>
  728. </div>
  729. <div class="paragraph">
  730. <p>The complete list of global uniforms that can be used in JME3 can be found <a href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/shader/UniformBinding.java">here</a>.+</p>
  731. </div>
  732. <div class="paragraph">
  733. <p>+</p>
  734. </div>
  735. </div>
  736. <div class="sect2">
  737. <h3 id="jme3-lighting-global-uniforms">JME3 Lighting Global uniforms</h3>
  738. <div class="paragraph">
  739. <p>JME3 uses some global uniforms for lighting :</p>
  740. </div>
  741. <div class="ulist">
  742. <ul>
  743. <li>
  744. <p>g_LightDirection (vec4) : the direction of the light</p>
  745. <div class="ulist">
  746. <ul>
  747. <li>
  748. <p>use for SpotLight : x,y,z contain the world direction vector of the light, the w component contains the spotlight angle cosine</p>
  749. </li>
  750. </ul>
  751. </div>
  752. </li>
  753. <li>
  754. <p>g_LightColor (vec4) : the color of the light</p>
  755. </li>
  756. <li>
  757. <p>g_LightPosition : the position of the light</p>
  758. <div class="ulist">
  759. <ul>
  760. <li>
  761. <p>use for SpotLight : x,y,z contain the world position of the light, the w component contains 1/lightRange</p>
  762. </li>
  763. <li>
  764. <p>use for PointLight : x,y,z contain the world position of the light, the w component contains 1/lightRadius</p>
  765. </li>
  766. <li>
  767. <p>use for DirectionalLight : strangely enough it&#8217;s used for the direction of the light…this might change though. The fourth component contains -1 and it&#8217;s used in the lighting shader to know if it&#8217;s a directionalLight or not.</p>
  768. </li>
  769. </ul>
  770. </div>
  771. </li>
  772. <li>
  773. <p>g_AmbientLightColor the color of the ambient light.</p>
  774. </li>
  775. </ul>
  776. </div>
  777. <div class="paragraph">
  778. <p>These uniforms are passed to the shader without having to declare them in the j3md file, but you have to specify in the technique definition “ LightMode MultiPass see lighting.j3md for more information.</p>
  779. </div>
  780. <div class="paragraph">
  781. <p>+</p>
  782. </div>
  783. </div>
  784. <div class="sect2">
  785. <h3 id="jme3-attributes">JME3 attributes</h3>
  786. <div class="paragraph">
  787. <p>Those are different attributes that are always passed to your shader.+</p>
  788. </div>
  789. <div class="paragraph">
  790. <p>You can find a complete list of those attribute in the Type enum of the VertexBuffer <a href="http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/VertexBuffer.java">here</a>.+</p>
  791. </div>
  792. <div class="paragraph">
  793. <p>Note that in the shader the attributes names will be prefixed by an “in”.+</p>
  794. </div>
  795. <div class="paragraph">
  796. <p>+</p>
  797. </div>
  798. <div class="paragraph">
  799. <p>When the enumeration lists some usual types for each attribute (for example texCoord specifies two floats) then that is the format expected by all standard JME3 shaders that use that attribute. When writing your own shaders though you can use alternative formats such as placing three floats in texCoord simply by declaring the attribute as vec3 in the shader and passing 3 as the component count into the mesh setBuffer call.</p>
  800. </div>
  801. </div>
  802. <div class="sect2">
  803. <h3 id="user-s-uniforms">User&#8217;s uniforms</h3>
  804. <div class="paragraph">
  805. <p>At some point when making your own shader you&#8217;ll need to pass your own uniforms+</p>
  806. </div>
  807. <div class="paragraph">
  808. <p>Any uniform has to be declared in the material definition file (.j3md) in the “MaterialParameters section.+</p>
  809. </div>
  810. <div class="listingblock">
  811. <div class="content">
  812. <pre class="CodeRay highlight"><code data-lang="java"> MaterialParameters {
  813. Vector4 <span class="predefined-type">Color</span>
  814. Texture2D ColorMap
  815. }</code></pre>
  816. </div>
  817. </div>
  818. <div class="paragraph">
  819. <p>You can also pass some define to your vertex/fragment programs to know if an uniform as been declared.<br></p>
  820. </div>
  821. <div class="paragraph">
  822. <p>You simply add it in the Defines section of your Technique in the definition file.<br></p>
  823. </div>
  824. <div class="listingblock">
  825. <div class="content">
  826. <pre class="CodeRay highlight"><code data-lang="java"> Defines {
  827. COLORMAP : ColorMap
  828. }</code></pre>
  829. </div>
  830. </div>
  831. <div class="paragraph">
  832. <p>For integer and floating point parameters, the define will contain the value that was set.+</p>
  833. </div>
  834. <div class="paragraph">
  835. <p>For all other types of parameters, the value 1 is defined.+</p>
  836. </div>
  837. <div class="paragraph">
  838. <p>If no value is set for that parameter, the define is not declared in the shader.+</p>
  839. </div>
  840. <div class="paragraph">
  841. <p>Those material parameters will be sent from the engine to the shader as follows,
  842. there are setXXXX methods for any type of uniform you want to pass.+</p>
  843. </div>
  844. <div class="listingblock">
  845. <div class="content">
  846. <pre class="CodeRay highlight"><code data-lang="java"> material.setColor(<span class="string"><span class="delimiter">&quot;</span><span class="content">Color</span><span class="delimiter">&quot;</span></span>, <span class="keyword">new</span> ColorRGBA(<span class="float">1.0f</span>, <span class="float">0.0f</span>, <span class="float">0.0f</span>, <span class="float">1.0f</span>); <span class="comment">// red color</span>
  847. material.setTexture(<span class="string"><span class="delimiter">&quot;</span><span class="content">ColorMap</span><span class="delimiter">&quot;</span></span>, myTexture); <span class="comment">// bind myTexture for that sampler uniform</span></code></pre>
  848. </div>
  849. </div>
  850. <div class="paragraph">
  851. <p>To use this uniform in the shader, you need to declare it in the .frag or .vert files (depending on where you need it).
  852. You can make use of the defines here and later in the code:
  853. <strong>Note that the “m_ prefix specifies that the uniform is a material parameter.</strong>+</p>
  854. </div>
  855. <div class="listingblock">
  856. <div class="content">
  857. <pre class="CodeRay highlight"><code data-lang="java"> uniform vec4 m_Color;
  858. <span class="error">#</span>ifdef COLORMAP
  859. uniform sampler2D m_ColorMap;
  860. <span class="error">#</span>endif</code></pre>
  861. </div>
  862. </div>
  863. <div class="paragraph">
  864. <p>The uniforms will be populated at runtime with the value you sent.</p>
  865. </div>
  866. </div>
  867. <div class="sect2">
  868. <h3 id="example-adding-color-keying-to-the-lighting-j3md-material-definition">Example: Adding Color Keying to the Lighting.j3md Material Definition</h3>
  869. <div class="paragraph">
  870. <p>Color Keying is useful in games involving many players. It consists of adding some<br></p>
  871. </div>
  872. <div class="paragraph">
  873. <p>player-specific color on models textures.<br></p>
  874. </div>
  875. <div class="paragraph">
  876. <p>The easiest way of doing this is to use a keyMap which will contain the amount of<br></p>
  877. </div>
  878. <div class="paragraph">
  879. <p>color to add in its alpha channel.<br></p>
  880. </div>
  881. <div class="paragraph">
  882. <p>Here I will use this color map: <a href="http://wstaw.org/m/2011/10/24/plasma-desktopxB2787.jpg">http://wstaw.org/m/2011/10/24/plasma-desktopxB2787.jpg</a><br></p>
  883. </div>
  884. <div class="paragraph">
  885. <p>to blend color on this texture: <a href="http://wstaw.org/m/2011/10/24/plasma-desktopbq2787.jpg">http://wstaw.org/m/2011/10/24/plasma-desktopbq2787.jpg</a><br></p>
  886. </div>
  887. <div class="paragraph">
  888. <p>+</p>
  889. </div>
  890. <div class="paragraph">
  891. <p>We need to pass 2 new parameters to the Lighting.j3md definition, MaterialParameters section :</p>
  892. </div>
  893. <div class="listingblock">
  894. <div class="content">
  895. <pre class="CodeRay highlight"><code data-lang="java"><span class="comment">// Keying Map</span>
  896. Texture2D KeyMap
  897. <span class="comment">// Key Color</span>
  898. <span class="predefined-type">Color</span> KeyColor</code></pre>
  899. </div>
  900. </div>
  901. <div class="paragraph">
  902. <p>Below, add a new Define in the main Technique section:</p>
  903. </div>
  904. <div class="listingblock">
  905. <div class="content">
  906. <pre class="CodeRay highlight"><code data-lang="java">KEYMAP : KeyMap</code></pre>
  907. </div>
  908. </div>
  909. <div class="paragraph">
  910. <p>In the Lighting.frag file, define the new uniforms:</p>
  911. </div>
  912. <div class="listingblock">
  913. <div class="content">
  914. <pre class="CodeRay highlight"><code data-lang="java"><span class="error">#</span>ifdef KEYMAP
  915. uniform sampler2D m_KeyMap;
  916. uniform vec4 m_KeyColor;
  917. <span class="error">#</span>endif</code></pre>
  918. </div>
  919. </div>
  920. <div class="paragraph">
  921. <p>Further, when obtaining the diffuseColor from the DiffuseMap texture, check
  922. if we need to blend it:</p>
  923. </div>
  924. <div class="listingblock">
  925. <div class="content">
  926. <pre class="CodeRay highlight"><code data-lang="java"> <span class="error">#</span>ifdef KEYMAP
  927. vec4 keyColor = texture2D(m_KeyMap, newTexCoord);
  928. diffuseColor.rgb = (<span class="float">1.0</span>-keyColor.a) * diffuseColor.rgb + keyColor.a * m_KeyColor.rgb;
  929. <span class="error">#</span>endif</code></pre>
  930. </div>
  931. </div>
  932. <div class="paragraph">
  933. <p>This way, a transparent pixel in the KeyMap texture doesn&#8217;t modify the color.<br></p>
  934. </div>
  935. <div class="paragraph">
  936. <p>A black pixel replaces it for the m_KeyColor and values in between are blended.+</p>
  937. </div>
  938. <div class="paragraph">
  939. <p>+</p>
  940. </div>
  941. <div class="paragraph">
  942. <p>A result preview can be seen here: <a href="http://wstaw.org/m/2011/10/24/plasma-desktopuV2787.jpg">http://wstaw.org/m/2011/10/24/plasma-desktopuV2787.jpg</a></p>
  943. </div>
  944. </div>
  945. <div class="sect2">
  946. <h3 id="step-by-step">Step by step</h3>
  947. <div class="ulist">
  948. <ul>
  949. <li>
  950. <p>Create a vertex shader (.vert) file</p>
  951. </li>
  952. <li>
  953. <p>Create a fragment shader (.frag) file</p>
  954. </li>
  955. <li>
  956. <p>Create a material definition (j3md) file specifying the user defined uniforms, path to the shaders and the global uniforms to use</p>
  957. </li>
  958. <li>
  959. <p>In your initSimpleApplication, create a material using this definition, apply it to a geometry</p>
  960. </li>
  961. <li>
  962. <p>That’s it!!</p>
  963. </li>
  964. </ul>
  965. </div>
  966. <div class="listingblock">
  967. <div class="content">
  968. <pre class="CodeRay highlight"><code data-lang="java"> <span class="comment">// A cube</span>
  969. <span class="predefined-type">Box</span> box= <span class="keyword">new</span> <span class="predefined-type">Box</span>(Vector3f.ZERO, <span class="float">1f</span>,<span class="float">1f</span>,<span class="float">1f</span>);
  970. Geometry cube = <span class="keyword">new</span> Geometry(<span class="string"><span class="delimiter">&quot;</span><span class="content">box</span><span class="delimiter">&quot;</span></span>, box);
  971. Material mat = <span class="keyword">new</span> Material(assetManager,<span class="string"><span class="delimiter">&quot;</span><span class="content">Path/To/My/materialDef.j3md</span><span class="delimiter">&quot;</span></span>);
  972. cube.setMaterial(mat);
  973. rootNode.attachChild(cube);</code></pre>
  974. </div>
  975. </div>
  976. <div class="paragraph">
  977. <p>+</p>
  978. </div>
  979. </div>
  980. <div class="sect2">
  981. <h3 id="jme3-and-opengl-3-4-compatibility">JME3 and OpenGL 3 &amp; 4 compatibility</h3>
  982. <div class="paragraph">
  983. <p>GLSL 1.0 to 1.2 comes with built in attributes and uniforms (ie, gl_Vertex, gl_ModelViewMatrix, etc…).+
  984. Those attributes are deprecated since GLSL 1.3 (opengl 3), hence JME3 global uniforms and attributes. Here is a list of deprecated attributes and their equivalent in JME3+</p>
  985. </div>
  986. <table class="tableblock frame-all grid-all spread">
  987. <colgroup>
  988. <col style="width: 50%;">
  989. <col style="width: 50%;">
  990. </colgroup>
  991. <thead>
  992. <tr>
  993. <th class="tableblock halign-left valign-top">GLSL 1.2 attributes</th>
  994. <th class="tableblock halign-left valign-top">JME3 equivalent</th>
  995. </tr>
  996. </thead>
  997. <tbody>
  998. <tr>
  999. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1000. <p>gl_Vertex</p>
  1001. </div></div></td>
  1002. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1003. <p>inPosition</p>
  1004. </div></div></td>
  1005. </tr>
  1006. <tr>
  1007. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1008. <p>gl_Normal</p>
  1009. </div></div></td>
  1010. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1011. <p>inNormal</p>
  1012. </div></div></td>
  1013. </tr>
  1014. <tr>
  1015. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1016. <p>gl_Color</p>
  1017. </div></div></td>
  1018. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1019. <p>inColor</p>
  1020. </div></div></td>
  1021. </tr>
  1022. <tr>
  1023. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1024. <p>gl_MultiTexCoord0</p>
  1025. </div></div></td>
  1026. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1027. <p>inTexCoord</p>
  1028. </div></div></td>
  1029. </tr>
  1030. <tr>
  1031. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1032. <p>gl_ModelViewMatrix</p>
  1033. </div></div></td>
  1034. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1035. <p>g_WorldViewMatrix</p>
  1036. </div></div></td>
  1037. </tr>
  1038. <tr>
  1039. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1040. <p>gl_ProjectionMatrix</p>
  1041. </div></div></td>
  1042. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1043. <p>g_ProjectionMatrix</p>
  1044. </div></div></td>
  1045. </tr>
  1046. <tr>
  1047. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1048. <p>gl_ModelViewProjectionMatrix</p>
  1049. </div></div></td>
  1050. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1051. <p>g_WorldViewProjectionMatrix</p>
  1052. </div></div></td>
  1053. </tr>
  1054. <tr>
  1055. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1056. <p>gl_NormalMatrix</p>
  1057. </div></div></td>
  1058. <td class="tableblock halign-left valign-top"><div><div class="paragraph">
  1059. <p>g_NormalMatrix</p>
  1060. </div></div></td>
  1061. </tr>
  1062. </tbody>
  1063. </table>
  1064. </div>
  1065. <div class="sect2">
  1066. <h3 id="useful-links">Useful links</h3>
  1067. <div class="paragraph">
  1068. <p><a href="http://www.eng.utah.edu/<sub>cs5610/lectures/GLSL-ATI-Intro.pdf"><a href="http://www.eng.utah.edu/" class="bare">http://www.eng.utah.edu/</a></sub>cs5610/lectures/GLSL-ATI-Intro.pdf</a></p>
  1069. </div>
  1070. </div>
  1071. </div>
  1072. <div id="footer">
  1073. <div id="footer-text">
  1074. Version <br>
  1075. Last updated 2016-06-05 15:58:32 UTC
  1076. </div>
  1077. </div>
  1078. </body>
  1079. </html>