scenegraph.js 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656
  1. /**
  2. * Copyright (C) 2014-2016 Triumph LLC
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. "use strict";
  18. /**
  19. * Rendering graph routines.
  20. *
  21. * Rendering graph consists of rendering subscenes, which in turn may have
  22. * zero or more inputs and one or more outputs. All subscenes must be closed
  23. * to last SINK element. SINK element is a fictional subscene without any outputs.
  24. *
  25. * @name scenegraph
  26. * @namespace
  27. * @exports exports as scenegraph
  28. */
  29. b4w.module["__scenegraph"] = function(exports, require) {
  30. var m_cam = require("__camera");
  31. var m_cfg = require("__config");
  32. var m_debug = require("__debug");
  33. var m_graph = require("__graph");
  34. var m_render = require("__renderer");
  35. var m_subs = require("__subscene");
  36. var m_tex = require("__textures");
  37. var m_util = require("__util");
  38. var cfg_dbg = m_cfg.debug_subs;
  39. var cfg_def = m_cfg.defaults;
  40. var cfg_scs = m_cfg.scenes;
  41. var DEBUG_DISABLE_TEX_REUSE = false;
  42. var LEFT_ONLY_SUBS_TYPES = [m_subs.GRASS_MAP, m_subs.SHADOW_CAST,
  43. m_subs.MAIN_CUBE_REFLECT,
  44. m_subs.MAIN_CUBE_REFLECT_BLEND];
  45. /**
  46. * Enforce uniqueness
  47. */
  48. function enforce_slink_uniqueness(graph, depth_tex) {
  49. var slinks = [];
  50. // make inter-subscene slinks unique
  51. m_graph.traverse_edges(graph, function(node1, node2, attr) {
  52. var slink = attr;
  53. if (slinks.indexOf(slink) > -1)
  54. m_graph.replace_edge_attr(graph, node1, node2, slink,
  55. clone_slink(slink));
  56. else
  57. slinks.push(slink);
  58. });
  59. m_graph.traverse(graph, function(id, attr) {
  60. var subs = attr;
  61. // make internal slinks unique
  62. for (var i = 0; i < subs.slinks_internal.length; i++) {
  63. var slink = subs.slinks_internal[i];
  64. if (!depth_tex && (subs.type == m_subs.MAIN_PLANE_REFLECT ||
  65. subs.type == m_subs.MAIN_CUBE_REFLECT ||
  66. subs.type == m_subs.MAIN_XRAY))
  67. slink.use_renderbuffer = true;
  68. if (slinks.indexOf(slink) > -1)
  69. subs.slinks_internal[i] = clone_slink(slink);
  70. else
  71. slinks.push(slink);
  72. }
  73. });
  74. }
  75. /**
  76. * Slinks compliance, etc
  77. */
  78. function enforce_graph_consistency(graph, depth_tex) {
  79. m_graph.traverse(graph, function(id, attr) {
  80. var subs = attr;
  81. // assign linear filtering to MOTION_BLUR accumulator
  82. // if such subscene connected to ANTIALIASING
  83. if (subs.type == m_subs.ANTIALIASING)
  84. m_graph.traverse_inputs(graph, id, function(id_in, attr_in,
  85. attr_edge) {
  86. var subs_in = attr_in;
  87. if (subs_in.type == m_subs.MOTION_BLUR) {
  88. for (var i = 0; i < subs_in.slinks_internal.length; i++) {
  89. var slink_mb_int = subs_in.slinks_internal[i];
  90. slink_mb_int.min_filter = m_tex.TF_LINEAR;
  91. slink_mb_int.mag_filter = m_tex.TF_LINEAR;
  92. }
  93. }
  94. });
  95. if (!depth_tex)
  96. m_graph.traverse_inputs(graph, id, function(id_in, attr_in,
  97. attr_edge) {
  98. var subs = attr_in;
  99. var slink = attr_edge;
  100. if (slink.from == "DEPTH")
  101. slink.use_renderbuffer = true;
  102. });
  103. });
  104. m_graph.traverse(graph, function(id, attr) {
  105. var subs = attr;
  106. var dest = {};
  107. combine_same_slinks(graph, id, dest);
  108. for (var i in dest) {
  109. var slinks = dest[i];
  110. // select maximum quality min filter
  111. var min_filt_slink = slinks[0];
  112. for (var j = 0; j < slinks.length; j++) {
  113. if (slinks[j].min_filter == m_tex.TF_LINEAR) {
  114. min_filt_slink = slinks[j];
  115. break;
  116. }
  117. }
  118. // select maximum quality mag filter
  119. var mag_filt_slink = slinks[0];
  120. for (var j = 0; j < slinks.length; j++) {
  121. if (slinks[j].mag_filter == m_tex.TF_LINEAR) {
  122. mag_filt_slink = slinks[j];
  123. break;
  124. }
  125. }
  126. // select non-renderbuffer
  127. var not_rb_slink = slinks[0];
  128. for (var j = 0; j < slinks.length; j++) {
  129. if (!slinks[j].use_renderbuffer) {
  130. not_rb_slink = slinks[j];
  131. break;
  132. }
  133. }
  134. // assign values from selected slinks
  135. for (var j = 0; j < slinks.length; j++) {
  136. slinks[j].min_filter = min_filt_slink.min_filter;
  137. slinks[j].mag_filter = mag_filt_slink.mag_filter;
  138. slinks[j].use_renderbuffer = not_rb_slink.use_renderbuffer;
  139. }
  140. }
  141. });
  142. }
  143. function combine_same_slinks(graph, id, dest) {
  144. m_graph.traverse_inputs(graph, id, function(id_in, attr_in,
  145. attr_edge) {
  146. var slink = attr_edge;
  147. // passive slink doesn't affect other
  148. if (!slink.active)
  149. return;
  150. if (slink.from == slink.to) {
  151. dest[slink.from] = dest[slink.from] || [];
  152. if (dest[slink.from].indexOf(slink) == -1)
  153. dest[slink.from].push(slink);
  154. combine_same_slinks(graph, id_in, dest);
  155. }
  156. });
  157. m_graph.traverse_outputs(graph, id, function(id_out, attr_out,
  158. attr_edge) {
  159. var slink = attr_edge;
  160. // passive slink doesn't affect other
  161. if (!slink.active)
  162. return;
  163. dest[slink.from] = dest[slink.from] || [];
  164. if (dest[slink.from].indexOf(slink) == -1)
  165. dest[slink.from].push(slink);
  166. });
  167. // special case: internal interchanges with output
  168. var subs = m_graph.get_node_attr(graph, id);
  169. if (subs.type == m_subs.MOTION_BLUR) {
  170. for (var i = 0; i < subs.slinks_internal.length; i++) {
  171. var slink = subs.slinks_internal[i];
  172. dest[slink.from].push(slink);
  173. }
  174. }
  175. }
  176. exports.check_slink_tex_conn = function(slink) {
  177. switch (slink.to) {
  178. case "COLOR":
  179. case "CUBEMAP":
  180. case "DEPTH":
  181. case "SCREEN":
  182. case "OFFSCREEN":
  183. case "RESOLVE":
  184. case "COPY":
  185. case "NONE":
  186. return false;
  187. default:
  188. return true;
  189. }
  190. }
  191. function process_subscene_links(graph) {
  192. // disable texture reuse for some scenes
  193. var FORCE_UNIQUE_TEXTURE_SUBS = [m_subs.MOTION_BLUR, m_subs.SMAA_RESOLVE,
  194. m_subs.SMAA_NEIGHBORHOOD_BLENDING, m_subs.MAIN_PLANE_REFLECT,
  195. m_subs.MAIN_CUBE_REFLECT, m_subs.PERFORMANCE];
  196. var graph_sorted = m_graph.topsort(graph);
  197. var tex_storage = [];
  198. m_graph.traverse(graph_sorted, function(id, attr) {
  199. var subs = attr;
  200. // assign new (or unused) internal textures
  201. for (var i = 0; i < subs.slinks_internal.length; i++) {
  202. var slink = subs.slinks_internal[i];
  203. if (FORCE_UNIQUE_TEXTURE_SUBS.indexOf(subs.type) > -1)
  204. slink.unique_texture = true;
  205. var tex = tex_aquire(tex_storage, slink,
  206. calc_slink_id(slink));
  207. slink.texture = tex;
  208. subs.textures_internal[i] = tex;
  209. }
  210. // release internal textures now
  211. for (var i = 0; i < subs.textures_internal.length; i++) {
  212. var tex = subs.textures_internal[i];
  213. tex_dec_ref(tex_storage, tex);
  214. }
  215. // connect new (or unused) external textures
  216. m_graph.traverse_outputs(graph_sorted, id, function(id_out, attr_out,
  217. attr_edge) {
  218. var slink = attr_edge;
  219. if (FORCE_UNIQUE_TEXTURE_SUBS.indexOf(subs.type) > -1)
  220. slink.unique_texture = true;
  221. if (slink.texture)
  222. return;
  223. var tex = find_nearest_tex(graph_sorted, id, slink.from);
  224. if (tex && slink.active && !slink.texture) {
  225. tex_inc_ref(tex_storage, tex);
  226. slink.texture = tex;
  227. return;
  228. }
  229. var tex = tex_aquire(tex_storage, slink,
  230. calc_slink_id(slink));
  231. slink.texture = tex;
  232. });
  233. // release unused textures from previous subscenes
  234. m_graph.traverse_inputs(graph_sorted, id, function(id_in, attr_in,
  235. attr_edge) {
  236. var slink = attr_edge;
  237. var subs_in = attr_in;
  238. tex_dec_ref(tex_storage, slink.texture);
  239. });
  240. // release unused non-connected textures
  241. m_graph.traverse_outputs(graph_sorted, id, function(id_out, attr_out,
  242. attr_edge) {
  243. var slink = attr_edge;
  244. if (slink.texture && slink.to == "NONE") {
  245. tex_dec_ref(tex_storage, slink.texture);
  246. }
  247. });
  248. });
  249. }
  250. function calc_slink_id(slink) {
  251. var id_obj = m_util.clone_object_json(slink);
  252. delete id_obj.to;
  253. delete id_obj.active;
  254. delete id_obj.texture;
  255. return JSON.stringify(id_obj);
  256. }
  257. function find_nearest_tex(graph, id, type) {
  258. var tex = null;
  259. m_graph.traverse_inputs(graph, id, function(id_in, attr_in,
  260. attr_edge) {
  261. var slink = attr_edge;
  262. if (slink.active && slink.from == slink.to && slink.from == type &&
  263. slink.texture) {
  264. tex = slink.texture;
  265. return true;
  266. }
  267. });
  268. m_graph.traverse_outputs(graph, id, function(id_out, attr_out,
  269. attr_edge) {
  270. var slink = attr_edge;
  271. if (slink.active && slink.from == type && slink.texture) {
  272. tex = slink.texture;
  273. return true;
  274. }
  275. });
  276. return tex;
  277. }
  278. function tex_inc_ref(storage, tex) {
  279. for (var i = 0; i < storage.length; i++) {
  280. var item = storage[i];
  281. if (item.tex === tex)
  282. item.ref++;
  283. }
  284. }
  285. function tex_dec_ref(storage, tex) {
  286. for (var i = 0; i < storage.length; i++) {
  287. var item = storage[i];
  288. if (item.tex === tex && item.ref)
  289. item.ref--;
  290. }
  291. }
  292. function tex_aquire(storage, slink, slink_id) {
  293. if (slink.parent_slink) {
  294. tex_inc_ref(storage, slink.parent_slink.texture);
  295. return slink.parent_slink.texture;
  296. }
  297. // a unique texture isn't presented in storage
  298. if (slink.unique_texture)
  299. return tex_create_for_slink(slink);
  300. var storage_item_free = null;
  301. // find first unused attachment
  302. for (var i = 0; i < storage.length; i++) {
  303. var item = storage[i];
  304. if (item.id == slink_id && item.ref === 0) {
  305. storage_item_free = item;
  306. break;
  307. }
  308. }
  309. if (storage_item_free && !(DEBUG_DISABLE_TEX_REUSE || cfg_def.firefox_tex_reuse_hack)) {
  310. storage_item_free.ref++;
  311. return storage_item_free.tex;
  312. } else {
  313. var tex = tex_create_for_slink(slink);
  314. storage.push({
  315. id: slink_id,
  316. ref: 1,
  317. tex: tex
  318. });
  319. return tex;
  320. }
  321. }
  322. function tex_create_for_slink(slink) {
  323. var size_x = slink.size_mult_x * slink.size;
  324. var size_y = slink.size_mult_y * slink.size;
  325. switch (slink.from) {
  326. case "COLOR":
  327. if (slink.use_renderbuffer) {
  328. var tex = m_tex.create_texture(slink.multisample ?
  329. m_tex.TT_RB_RGBA_MS : m_tex.TT_RB_RGBA, slink.use_comparison);
  330. m_tex.resize(tex, size_x, size_y);
  331. } else {
  332. var tex = m_tex.create_texture(m_tex.TT_RGBA_INT,
  333. slink.use_comparison);
  334. m_tex.resize(tex, size_x, size_y);
  335. m_tex.set_filters(tex, slink.min_filter, slink.mag_filter);
  336. }
  337. return tex;
  338. case "DEPTH":
  339. if (slink.use_renderbuffer) {
  340. var tex = m_tex.create_texture(slink.multisample ?
  341. m_tex.TT_RB_DEPTH_MS : m_tex.TT_RB_DEPTH,
  342. slink.use_comparison);
  343. m_tex.resize(tex, size_x, size_y);
  344. } else {
  345. var tex = m_tex.create_texture(m_tex.TT_DEPTH, slink.use_comparison);
  346. m_tex.resize(tex, size_x, size_y);
  347. m_tex.set_filters(tex, slink.min_filter, slink.mag_filter);
  348. }
  349. return tex;
  350. case "CUBEMAP":
  351. var tex = m_tex.create_cubemap_texture(size_x);
  352. return tex;
  353. case "SCREEN":
  354. case "NONE":
  355. return null;
  356. default:
  357. m_util.panic("Wrong slink param: " + slink.from);
  358. }
  359. }
  360. exports.traverse_slinks = traverse_slinks;
  361. /**
  362. */
  363. function traverse_slinks(graph, callback) {
  364. var exit = false;
  365. // process slinks assigned as inter-subscene edges
  366. m_graph.traverse_edges(graph, function(node1, node2, attr) {
  367. var slink = attr;
  368. if (!slink)
  369. return;
  370. var subs1 = m_graph.get_node_attr(graph, node1);
  371. var subs2 = m_graph.get_node_attr(graph, node2);
  372. if (callback(slink, false, subs1, subs2)) {
  373. exit = true;
  374. return true;
  375. }
  376. });
  377. if (exit)
  378. return;
  379. // process internal slinks
  380. m_graph.traverse(graph, function(node, attr) {
  381. var subs = attr;
  382. for (var i = 0; i < subs.slinks_internal.length; i++) {
  383. var slink = subs.slinks_internal[i];
  384. if (callback(slink, true, subs, null))
  385. return true;
  386. }
  387. });
  388. }
  389. function assign_render_targets(graph) {
  390. m_graph.traverse(graph, function(nid, subs) {
  391. if (subs.type == m_subs.SINK)
  392. return;
  393. var cam = subs.camera;
  394. m_graph.traverse_outputs(graph, nid, function(nid_out, subs_out,
  395. slink) {
  396. if (slink.active && slink.texture) {
  397. m_cam.set_attachment(cam, slink.from, slink.texture);
  398. if (slink.from == slink.to && subs_out.camera)
  399. m_cam.set_attachment(subs_out.camera, slink.from, slink.texture);
  400. }
  401. });
  402. for (var i = 0; i < subs.slinks_internal.length; i++) {
  403. var slink = subs.slinks_internal[i];
  404. if (slink.active && slink.from == slink.to) {
  405. var tex = subs.textures_internal[i];
  406. m_cam.set_attachment(cam, slink.from, tex);
  407. }
  408. }
  409. if ((cam.color_attachment || cam.depth_attachment) && !cam.framebuffer)
  410. cam.framebuffer = m_render.render_target_create(cam.color_attachment,
  411. cam.depth_attachment);
  412. });
  413. m_graph.traverse(graph, function(nid, subs) {
  414. if (subs.type == m_subs.RESOLVE || subs.type == m_subs.COPY) {
  415. var inputs = get_inputs(graph, subs);
  416. var cam = subs.camera;
  417. cam.framebuffer_prev = inputs[0].camera.framebuffer;
  418. }
  419. });
  420. }
  421. /**
  422. * Prepare full-featured rendering graph for given scene render.
  423. * @param {Object3D} sc_render Scene render object
  424. * @param {Object3D} cam_scene_data Camera scene data
  425. * @param {Object3D} cam_render Camera render object
  426. * @param {Boolean} render_to_textures Textures for offscreen rendering
  427. * @returns Rendering graph
  428. */
  429. exports.create_rendering_graph = function(sc_render, cam_scene_data,
  430. cam_render, render_to_textures) {
  431. var graph = m_graph.create();
  432. // subscenes from previous level
  433. var prev_level = [];
  434. // currently populated level
  435. var curr_level = [];
  436. // shared
  437. var shadow_subscenes = [];
  438. var shadow_links = [];
  439. var reflect_subscenes = [];
  440. var reflect_links = [];
  441. var cube_refl_subscenes = [];
  442. var cube_reflect_links = [];
  443. var num_lights = sc_render.lamps_number;
  444. var water_params = sc_render.water_params;
  445. var shore_smoothing = sc_render.shore_smoothing;
  446. var soft_particles = sc_render.soft_particles;
  447. var ssao = sc_render.ssao;
  448. var god_rays = sc_render.god_rays;
  449. var refl_params = sc_render.reflection_params;
  450. var mat_params = sc_render.materials_params;
  451. var bloom_params = sc_render.bloom_params;
  452. var motion_blur = sc_render.motion_blur;
  453. var compositing = sc_render.compositing;
  454. var antialiasing = sc_render.antialiasing;
  455. var wls_params = sc_render.world_light_set;
  456. var wfs_params = sc_render.world_fog_set;
  457. var shadow_params = sc_render.shadow_params;
  458. var mb_params = sc_render.mb_params;
  459. var cc_params = sc_render.cc_params;
  460. var gr_params = sc_render.god_rays_params;
  461. var outline_params = sc_render.outline_params;
  462. var dof = sc_render.dof;
  463. var depth_tex = sc_render.depth_tex;
  464. var refractions = sc_render.refractions;
  465. var rtt = Boolean(render_to_textures.length);
  466. var msaa = cfg_def.msaa_samples > 1;
  467. var slink_color_o = create_slink("COLOR", "COLOR", 1, 1, 1, true);
  468. var slink_depth_o = create_slink("DEPTH", "DEPTH", 1, 1, 1, true);
  469. if (msaa) {
  470. var slink_color_resolve_o = clone_slink(slink_depth_o);
  471. var slink_depth_resolve_o = clone_slink(slink_depth_o);
  472. slink_color_o.multisample = true;
  473. slink_color_o.use_renderbuffer = true;
  474. slink_depth_o.multisample = true;
  475. slink_depth_o.use_renderbuffer = true;
  476. }
  477. var main_cam = cam_scene_data.cameras[0];
  478. // shadow stuff
  479. if (shadow_params) {
  480. m_cam.update_camera_shadows(main_cam, shadow_params);
  481. for (var j = 0; j < shadow_params.lamp_types.length; j++) {
  482. var csm_num = shadow_params.csm_num;
  483. for (var i = 0; i < csm_num; i++) {
  484. var subs_shadow = m_subs.create_subs_shadow_cast(i, j, shadow_params, num_lights);
  485. m_graph.append_node_attr(graph, subs_shadow);
  486. shadow_subscenes.push(subs_shadow);
  487. var tex_size = shadow_params.csm_resolution;
  488. var cam = subs_shadow.camera;
  489. // NOTE: shadow cameras used in LOD shadows calculations
  490. cam_scene_data.shadow_cameras.push(cam);
  491. cam.width = tex_size;
  492. cam.height = tex_size;
  493. subs_shadow.clear_color = false;
  494. // NOTE: we use one lamp with csm or a lot of cast lamps
  495. var index = j > 0 ? j : i;
  496. var depth_slink = create_slink("DEPTH", "u_shadow_map" + index,
  497. tex_size, 1, 1, false);
  498. if (cfg_def.compared_mode_depth) {
  499. depth_slink.min_filter = m_tex.TF_LINEAR;
  500. depth_slink.mag_filter = m_tex.TF_LINEAR;
  501. depth_slink.use_comparison = true;
  502. }
  503. shadow_links.push(depth_slink);
  504. if (m_debug.check_depth_only_issue() || cfg_def.shadows_color_slink_hack) {
  505. subs_shadow.slinks_internal.push(create_slink("COLOR",
  506. "COLOR", tex_size, 1, 1, false));
  507. }
  508. }
  509. }
  510. }
  511. // cube reflections
  512. if (refl_params && refl_params.num_cube_refl && !rtt) {
  513. for (var i = 0; i < refl_params.num_cube_refl; i++) {
  514. var cam = m_cam.create_camera(m_cam.TYPE_PERSP);
  515. cam.width = sc_render.cubemap_refl_size;
  516. cam.height = sc_render.cubemap_refl_size;
  517. m_cam.set_frustum(cam, 90, 0.1, 100);
  518. m_cam.set_projection(cam, cam.aspect);
  519. var subs_refl = m_subs.create_subs_main(m_subs.MAIN_CUBE_REFLECT, cam, false,
  520. water_params, num_lights, wfs_params, wls_params, null, sc_render.sun_exist);
  521. subs_refl.cube_view_matrices = m_util.generate_inv_cubemap_matrices();
  522. for (var j = 0; j < 6; j++)
  523. subs_refl.cube_cam_frustums.push(m_cam.create_frustum_planes());
  524. m_graph.append_node_attr(graph, subs_refl);
  525. var slink_refl_c = create_slink("CUBEMAP", "u_cube_reflection",
  526. sc_render.cubemap_refl_size, 1, 1, false);
  527. slink_refl_c.min_filter = m_tex.TF_LINEAR;
  528. slink_refl_c.mag_filter = m_tex.TF_LINEAR;
  529. cube_reflect_links.push(slink_refl_c);
  530. if (refl_params.has_blend_reflexible) {
  531. var subs_refl_blend = m_subs.create_subs_main(m_subs.MAIN_CUBE_REFLECT_BLEND, cam, false,
  532. water_params, num_lights, wfs_params, wls_params, null, sc_render.sun_exist);
  533. subs_refl_blend.cube_view_matrices = subs_refl.cube_view_matrices;
  534. subs_refl_blend.cube_cam_frustums = subs_refl.cube_cam_frustums;
  535. m_graph.append_node_attr(graph, subs_refl_blend);
  536. var slink_depth_refl = create_slink("DEPTH", "DEPTH",
  537. sc_render.cubemap_refl_size, 1, 1, false);
  538. var slink_color_refl = create_slink("COLOR", "COLOR",
  539. sc_render.cubemap_refl_size, 1, 1, false);
  540. m_graph.append_edge_attr(graph, subs_refl, subs_refl_blend, slink_depth_refl);
  541. m_graph.append_edge_attr(graph, subs_refl, subs_refl_blend, slink_color_refl);
  542. cube_refl_subscenes.push(subs_refl_blend);
  543. refl_params.cube_refl_subs_blend.push(subs_refl_blend);
  544. } else {
  545. var slink_refl_d = create_slink("DEPTH", "DEPTH",
  546. sc_render.cubemap_refl_size, 1, 1, false);
  547. subs_refl.slinks_internal.push(slink_refl_d);
  548. cube_refl_subscenes.push(subs_refl);
  549. }
  550. refl_params.cube_refl_subs.push(subs_refl);
  551. }
  552. }
  553. // plane reflections
  554. if (refl_params && refl_params.refl_plane_objs.length > 0 && !rtt) {
  555. for (var j = 0; j < refl_params.refl_plane_objs.length; j++) {
  556. var cam = m_cam.clone_camera(main_cam, true);
  557. cam.reflection_plane = new Float32Array(4);
  558. cam_scene_data.cameras.push(cam);
  559. var subs_refl = m_subs.create_subs_main(m_subs.MAIN_PLANE_REFLECT, cam, false,
  560. water_params, num_lights, wfs_params, wls_params,
  561. null, sc_render.sun_exist);
  562. m_graph.append_node_attr(graph, subs_refl);
  563. var slink_refl_c = create_slink("COLOR", "u_plane_reflection", 1,
  564. sc_render.plane_refl_size,
  565. sc_render.plane_refl_size, true);
  566. slink_refl_c.min_filter = m_tex.TF_LINEAR;
  567. slink_refl_c.mag_filter = m_tex.TF_LINEAR;
  568. reflect_links.push(slink_refl_c);
  569. if (refl_params.has_blend_reflexible) {
  570. var subs_refl_blend = m_subs.create_subs_main(m_subs.MAIN_PLANE_REFLECT_BLEND,
  571. cam, false, water_params, num_lights, wfs_params,
  572. wls_params, null, sc_render.sun_exist);
  573. m_graph.append_node_attr(graph, subs_refl_blend);
  574. var slink_depth_refl = create_slink("DEPTH", "DEPTH", 1,
  575. sc_render.plane_refl_size,
  576. sc_render.plane_refl_size, true);
  577. var slink_color_refl = create_slink("COLOR", "COLOR", 1,
  578. sc_render.plane_refl_size,
  579. sc_render.plane_refl_size, true);
  580. slink_color_refl.min_filter = m_tex.TF_NEAREST;
  581. slink_color_refl.mag_filter = m_tex.TF_NEAREST;
  582. m_graph.append_edge_attr(graph, subs_refl, subs_refl_blend, slink_depth_refl);
  583. m_graph.append_edge_attr(graph, subs_refl, subs_refl_blend, slink_color_refl);
  584. refl_params.plane_refl_subs_blend.push([subs_refl_blend]);
  585. reflect_subscenes.push(subs_refl_blend);
  586. } else {
  587. var slink_refl_d = create_slink("DEPTH", "DEPTH", 1,
  588. sc_render.plane_refl_size,
  589. sc_render.plane_refl_size, true);
  590. subs_refl.slinks_internal.push(slink_refl_d);
  591. reflect_subscenes.push(subs_refl);
  592. }
  593. refl_params.plane_refl_subs.push([subs_refl]);
  594. }
  595. }
  596. // dynamic grass
  597. if (sc_render.dynamic_grass) {
  598. var subs_grass_map = m_subs.create_subs_grass_map();
  599. m_graph.append_node_attr(graph, subs_grass_map);
  600. var tex_size = cfg_scs.grass_tex_size;
  601. // NOTE: deprecated
  602. subs_grass_map.camera.width = tex_size;
  603. subs_grass_map.camera.height = tex_size;
  604. var slink_grass_map_d = create_slink("DEPTH", "u_grass_map_depth",
  605. tex_size, 1, 1, false);
  606. if (!cfg_def.webgl2) {
  607. slink_grass_map_d.min_filter = m_tex.TF_LINEAR;
  608. slink_grass_map_d.mag_filter = m_tex.TF_LINEAR;
  609. }
  610. // NOTE: need to be optional?
  611. var slink_grass_map_c = create_slink("COLOR", "u_grass_map_color",
  612. tex_size, 1, 1, false);
  613. slink_grass_map_c.min_filter = m_tex.TF_LINEAR;
  614. slink_grass_map_c.mag_filter = m_tex.TF_LINEAR;
  615. } else {
  616. var subs_grass_map = null;
  617. var slink_grass_map_d = null;
  618. var slink_grass_map_c = null;
  619. }
  620. // depth
  621. if (depth_tex && shadow_params) {
  622. var cam_sh_receive = m_cam.clone_camera(main_cam, true);
  623. cam_scene_data.cameras.push(cam_sh_receive);
  624. var subs_receive = m_subs.create_subs_shadow_receive(graph, cam_sh_receive, num_lights);
  625. m_graph.append_node_attr(graph, subs_receive);
  626. subs_receive.self_shadow_normal_offset = shadow_params.self_shadow_normal_offset;
  627. for (var i = 0; i < shadow_subscenes.length; i++) {
  628. var subs_shadow = shadow_subscenes[i];
  629. var slink_shadow = shadow_links[i];
  630. m_graph.append_edge_attr(graph, subs_shadow, subs_receive, slink_shadow);
  631. }
  632. var slink_depth_c = create_slink("COLOR", "u_color", 1, 1, 1, true);
  633. var slink_depth_d = create_slink("DEPTH", "u_depth", 1, 1, 1, true);
  634. if (ssao) {
  635. // ssao
  636. var cam_ssao = m_cam.clone_camera(main_cam, true);
  637. cam_scene_data.cameras.push(cam_ssao);
  638. var ssao_params = sc_render.ssao_params;
  639. var subs_ssao = m_subs.create_subs_ssao(cam_ssao, wfs_params, ssao_params);
  640. m_graph.append_node_attr(graph, subs_ssao);
  641. var slink_ssao = create_slink("COLOR", "u_ssao_mask", 1, 1, 1, true);
  642. m_graph.append_edge_attr(graph, subs_receive, subs_ssao, slink_depth_c);
  643. m_graph.append_edge_attr(graph, subs_receive, subs_ssao, slink_depth_d);
  644. // ssao_blur
  645. var cam_ssao_blur = m_cam.clone_camera(main_cam, true);
  646. cam_scene_data.cameras.push(cam_ssao_blur);
  647. var subs_ssao_blur = m_subs.create_subs_ssao_blur(cam_ssao_blur, ssao_params);
  648. m_graph.append_node_attr(graph, subs_ssao_blur);
  649. var slink_ssao_blur = create_slink("COLOR", "u_shadow_mask", 1, 1, 1, true);
  650. m_graph.append_edge_attr(graph, subs_ssao, subs_ssao_blur, slink_ssao);
  651. m_graph.append_edge_attr(graph, subs_receive, subs_ssao_blur, slink_depth_d);
  652. }
  653. if (msaa)
  654. subs_receive.slinks_internal.push(create_slink("DEPTH", "DEPTH", 1, 1, 1, true));
  655. else
  656. subs_receive.slinks_internal.push(slink_depth_o);
  657. if (subs_grass_map) {
  658. m_graph.append_edge_attr(graph, subs_grass_map, subs_receive,
  659. slink_grass_map_d);
  660. m_graph.append_edge_attr(graph, subs_grass_map, subs_receive,
  661. slink_grass_map_c);
  662. }
  663. } else
  664. var subs_receive = null;
  665. // main opaque
  666. var subs_main_opaque = m_subs.create_subs_main(m_subs.MAIN_OPAQUE, main_cam, true,
  667. water_params, num_lights, wfs_params, wls_params, null,
  668. sc_render.sun_exist);
  669. m_graph.append_node_attr(graph, subs_main_opaque);
  670. if (msaa) {
  671. var subs_res_opaque = m_subs.create_subs_resolve();
  672. m_graph.append_node_attr(graph, subs_res_opaque);
  673. curr_level.push(subs_res_opaque);
  674. var slink_resolve_in_c = create_slink("COLOR", "RESOLVE", 1, 1, 1, true);
  675. slink_resolve_in_c.multisample = true;
  676. slink_resolve_in_c.use_renderbuffer = true;
  677. var slink_resolve_in_d = create_slink("DEPTH", "RESOLVE", 1, 1, 1, true);
  678. slink_resolve_in_d.multisample = true;
  679. slink_resolve_in_d.use_renderbuffer = true;
  680. m_graph.append_edge_attr(graph, subs_main_opaque, subs_res_opaque, slink_resolve_in_c);
  681. m_graph.append_edge_attr(graph, subs_main_opaque, subs_res_opaque, slink_resolve_in_d);
  682. if (subs_receive) {
  683. if (slink_ssao)
  684. m_graph.append_edge_attr(graph, subs_ssao_blur, subs_main_opaque, slink_ssao_blur);
  685. else if (shadow_params)
  686. m_graph.append_edge_attr(graph, subs_receive, subs_main_opaque,
  687. create_slink("COLOR", "u_shadow_mask", 1, 1, 1, true));
  688. else
  689. m_util.panic("Internal error");
  690. }
  691. } else {
  692. curr_level.push(subs_main_opaque);
  693. if (subs_receive) {
  694. if (slink_ssao)
  695. m_graph.append_edge_attr(graph, subs_ssao_blur, subs_main_opaque, slink_ssao_blur);
  696. else if (shadow_params)
  697. m_graph.append_edge_attr(graph, subs_receive, subs_main_opaque,
  698. create_slink("COLOR", "u_shadow_mask", 1, 1, 1, true));
  699. else
  700. m_util.panic("Internal error");
  701. }
  702. }
  703. if (subs_grass_map) {
  704. m_graph.append_edge_attr(graph, subs_grass_map, subs_main_opaque,
  705. slink_grass_map_d);
  706. m_graph.append_edge_attr(graph, subs_grass_map, subs_main_opaque,
  707. slink_grass_map_c);
  708. }
  709. if (reflect_subscenes.length) {
  710. var num_refl_subs = reflect_subscenes.length;
  711. for (var j = 0; j < num_refl_subs; j++) {
  712. m_graph.append_edge_attr(graph,
  713. reflect_subscenes[j], subs_main_opaque,
  714. reflect_links[j]);
  715. }
  716. }
  717. if (cube_refl_subscenes.length) {
  718. for (var j = 0; j < cube_refl_subscenes.length; j++) {
  719. m_graph.append_edge_attr(graph, cube_refl_subscenes[j], subs_main_opaque,
  720. cube_reflect_links[j]);
  721. }
  722. }
  723. prev_level = curr_level;
  724. curr_level = [];
  725. if (!rtt && sc_render.color_picking) {
  726. var cam = m_cam.clone_camera(main_cam, true);
  727. cam.width = 1;
  728. cam.height = 1;
  729. // camera depends on bpy camera
  730. cam_scene_data.cameras.push(cam);
  731. var subs_color_picking = m_subs.create_subs_color_picking(cam, false, num_lights);
  732. m_graph.append_node_attr(graph, subs_color_picking);
  733. if (sc_render.xray) {
  734. var cam = m_cam.clone_camera(main_cam, true);
  735. cam.width = 1;
  736. cam.height = 1;
  737. cam_scene_data.cameras.push(cam);
  738. var subs_color_picking_xray = m_subs.create_subs_color_picking(cam, true, num_lights);
  739. m_graph.append_node_attr(graph, subs_color_picking_xray);
  740. var cp_slink_c = create_slink("COLOR", "COLOR", 1, 1, 1, false);
  741. m_graph.append_edge_attr(graph, subs_color_picking,
  742. subs_color_picking_xray, cp_slink_c);
  743. var cp_slink_d = create_slink("DEPTH", "DEPTH", 1, 1, 1, false);
  744. m_graph.append_edge_attr(graph, subs_color_picking,
  745. subs_color_picking_xray, cp_slink_d);
  746. }
  747. } else
  748. var subs_color_picking = null;
  749. // refraction subscene
  750. if ((mat_params.refractions || refractions) && !rtt) {
  751. if (!msaa) {
  752. var subs_refr = m_subs.create_subs_copy();
  753. m_graph.append_node_attr(graph, subs_refr);
  754. var slink_refr_in = create_slink("COLOR", "COPY", 1, 1, 1, true);
  755. m_graph.append_edge_attr(graph, prev_level[0], subs_refr, slink_refr_in);
  756. } else
  757. var subs_refr = subs_res_opaque;
  758. var slink_refr = create_slink("COLOR", "u_refractmap", 1, 1, 1, true);
  759. } else
  760. var subs_refr = null;
  761. if (depth_tex && (refractions || shore_smoothing || soft_particles)) {
  762. var cam_depth_pack = m_cam.clone_camera(main_cam, true);
  763. cam_scene_data.cameras.push(cam_depth_pack);
  764. var subs_depth_pack = m_subs.create_subs_depth_pack(cam_depth_pack);
  765. m_graph.append_node_attr(graph, subs_depth_pack);
  766. var slink_depth_pack_in = create_slink("DEPTH", "u_depth", 1, 1, 1, true);
  767. m_graph.append_edge_attr(graph, msaa ? subs_res_opaque : subs_main_opaque,
  768. subs_depth_pack, slink_depth_pack_in);
  769. var slink_depth_pack_out = create_slink("COLOR", "u_scene_depth", 1, 1, 1, true);
  770. // disable filtering for packed depth
  771. slink_depth_pack_out.min_filter = m_tex.TF_NEAREST;
  772. slink_depth_pack_out.mag_filter = m_tex.TF_NEAREST;
  773. } else
  774. var subs_depth_pack = null;
  775. // to prevent code duplication
  776. var create_custom_sub_main = function(type) {
  777. var cam = m_cam.clone_camera(main_cam, true);
  778. cam_scene_data.cameras.push(cam);
  779. var subs_main = m_subs.create_subs_main(type, cam, false, water_params,
  780. num_lights, wfs_params, wls_params, shadow_params, sc_render.sun_exist);
  781. m_graph.append_node_attr(graph, subs_main);
  782. if (type == m_subs.MAIN_XRAY) {
  783. // NOTE: disable MSAA
  784. var slink_color = create_slink("COLOR", "COLOR", 1, 1, 1, true);
  785. m_graph.append_edge_attr(graph, prev_level[0], subs_main, slink_color);
  786. var slink_depth = create_slink("DEPTH", "DEPTH", 1, 1, 1, true);
  787. subs_main.slinks_internal.push(slink_depth);
  788. } else {
  789. // NOTE: it's possible to do better
  790. if (msaa && prev_level[0].type == m_subs.RESOLVE)
  791. var subs_prev = subs_main_opaque;
  792. else
  793. var subs_prev = prev_level[0];
  794. m_graph.append_edge_attr(graph, subs_prev, subs_main,
  795. slink_depth_o);
  796. m_graph.append_edge_attr(graph, subs_prev, subs_main, slink_color_o);
  797. }
  798. if (subs_grass_map) {
  799. m_graph.append_edge_attr(graph, subs_grass_map, subs_main,
  800. slink_grass_map_d);
  801. m_graph.append_edge_attr(graph, subs_grass_map, subs_main,
  802. slink_grass_map_c);
  803. }
  804. for (var i = 0; i < shadow_subscenes.length; i++) {
  805. var subs_shadow = shadow_subscenes[i];
  806. var slink_shadow = shadow_links[i];
  807. m_graph.append_edge_attr(graph, subs_shadow, subs_main, slink_shadow);
  808. }
  809. if (subs_depth_pack)
  810. m_graph.append_edge_attr(graph, subs_depth_pack, subs_main,
  811. slink_depth_pack_out);
  812. if (reflect_subscenes.length) {
  813. var num_refl_subs = reflect_subscenes.length;
  814. for (var i = 0; i < num_refl_subs; i++)
  815. m_graph.append_edge_attr(graph, reflect_subscenes[i],
  816. subs_main, reflect_links[i]);
  817. }
  818. if (cube_refl_subscenes.length) {
  819. for (var i = 0; i < cube_refl_subscenes.length; i++) {
  820. m_graph.append_edge_attr(graph, cube_refl_subscenes[i], subs_main,
  821. cube_reflect_links[i]);
  822. }
  823. }
  824. if (subs_refr)
  825. m_graph.append_edge_attr(graph, subs_refr, subs_main, slink_refr);
  826. return subs_main;
  827. }
  828. if (sc_render.glow_over_blend) {
  829. var subs_main_blend = create_custom_sub_main(m_subs.MAIN_BLEND)
  830. curr_level.push(subs_main_blend);
  831. prev_level = curr_level;
  832. curr_level = [];
  833. }
  834. // main glow
  835. if (sc_render.glow_materials) {
  836. var cam_glow = m_cam.clone_camera(main_cam, true);
  837. cam_scene_data.cameras.push(cam_glow);
  838. var subs_main_glow = m_subs.create_subs_main(m_subs.MAIN_GLOW, cam_glow, false, water_params,
  839. num_lights, wfs_params, wls_params);
  840. m_graph.append_node_attr(graph, subs_main_glow);
  841. // link some uniforms likewise for the MAIN_OPAQUE subscene
  842. if (subs_depth_pack)
  843. m_graph.append_edge_attr(graph, subs_depth_pack, subs_main_glow,
  844. slink_depth_pack_out);
  845. if (subs_refr)
  846. m_graph.append_edge_attr(graph, subs_refr, subs_main_glow, slink_refr);
  847. if (subs_grass_map) {
  848. m_graph.append_edge_attr(graph, subs_grass_map, subs_main_glow,
  849. slink_grass_map_d);
  850. m_graph.append_edge_attr(graph, subs_grass_map, subs_main_glow,
  851. slink_grass_map_c);
  852. }
  853. if (reflect_subscenes.length) {
  854. var num_refl_subs = reflect_subscenes.length;
  855. for (var j = 0; j < num_refl_subs; j++) {
  856. m_graph.append_edge_attr(graph,
  857. reflect_subscenes[j], subs_main_glow,
  858. reflect_links[j]);
  859. }
  860. }
  861. if (cube_refl_subscenes.length) {
  862. for (var j = 0; j < cube_refl_subscenes.length; j++) {
  863. m_graph.append_edge_attr(graph, cube_refl_subscenes[j], subs_main_glow,
  864. cube_reflect_links[j]);
  865. }
  866. }
  867. m_graph.append_edge_attr(graph, msaa ? subs_res_opaque : subs_main_opaque,
  868. subs_main_glow, msaa ? slink_depth_resolve_o : slink_depth_o);
  869. var blur_x = m_subs.create_subs_postprocessing("X_GLOW_BLUR");
  870. blur_x.subtype = "GLOW_MASK_SMALL";
  871. set_texel_size_mult(blur_x, sc_render.glow_params.small_glow_mask_width);
  872. var slink_blur_x = create_slink("COLOR", "u_color", 1, 1, 1, true);
  873. slink_blur_x.min_filter = m_tex.TF_LINEAR;
  874. slink_blur_x.mag_filter = m_tex.TF_LINEAR;
  875. m_graph.append_node_attr(graph, blur_x);
  876. m_graph.append_edge_attr(graph, subs_main_glow, blur_x, slink_blur_x);
  877. var blur_y = m_subs.create_subs_postprocessing("Y_GLOW_BLUR");
  878. blur_y.subtype = "GLOW_MASK_SMALL";
  879. set_texel_size_mult(blur_y, sc_render.glow_params.small_glow_mask_width);
  880. var slink_blur_y = create_slink("COLOR", "u_color", 1, 0.5, 0.5, true);
  881. slink_blur_y.min_filter = m_tex.TF_LINEAR;
  882. slink_blur_y.mag_filter = m_tex.TF_LINEAR;
  883. m_graph.append_node_attr(graph, blur_y);
  884. m_graph.append_edge_attr(graph, blur_x, blur_y, slink_blur_y);
  885. var blur_x2 = m_subs.create_subs_postprocessing("X_GLOW_BLUR");
  886. blur_x2.subtype = "GLOW_MASK_LARGE";
  887. set_texel_size_mult(blur_x2, sc_render.glow_params.large_glow_mask_width);
  888. var slink_blur_x2 = create_slink("COLOR", "u_color", 1, 0.5, 0.5, true);
  889. slink_blur_x2.min_filter = m_tex.TF_LINEAR;
  890. slink_blur_x2.mag_filter = m_tex.TF_LINEAR;
  891. m_graph.append_node_attr(graph, blur_x2);
  892. m_graph.append_edge_attr(graph, blur_y, blur_x2, slink_blur_x2);
  893. var blur_y2 = m_subs.create_subs_postprocessing("Y_GLOW_BLUR");
  894. blur_y2.subtype = "GLOW_MASK_LARGE";
  895. set_texel_size_mult(blur_y2, sc_render.glow_params.large_glow_mask_width);
  896. var slink_blur_y2 = create_slink("COLOR", "u_color", 1, 0.25, 0.25, true);
  897. slink_blur_y2.min_filter = m_tex.TF_LINEAR;
  898. slink_blur_y2.mag_filter = m_tex.TF_LINEAR;
  899. m_graph.append_node_attr(graph, blur_y2);
  900. m_graph.append_edge_attr(graph, blur_x2, blur_y2, slink_blur_y2);
  901. var cam_glow_combine = m_cam.clone_camera(main_cam, true);
  902. cam_scene_data.cameras.push(cam_glow_combine);
  903. var subs_glow_combine = m_subs.create_subs_glow_combine(cam_glow_combine, sc_render);
  904. m_graph.append_node_attr(graph, subs_glow_combine);
  905. var slink_c_src = create_slink("COLOR", "u_src_color", 1, 1, 1, true);
  906. if (sc_render.glow_over_blend) {
  907. if (msaa) {
  908. // NOTE: redundant resolve, place the scene below debug_view or so
  909. var subs_res_blend = m_subs.create_subs_resolve();
  910. m_graph.append_node_attr(graph, subs_res_blend);
  911. m_graph.append_edge_attr(graph, subs_main_blend, subs_res_blend,
  912. slink_resolve_in_c);
  913. m_graph.append_edge_attr(graph, subs_main_blend, subs_res_blend,
  914. slink_resolve_in_d);
  915. m_graph.append_edge_attr(graph, subs_res_blend, subs_glow_combine, slink_c_src);
  916. } else
  917. m_graph.append_edge_attr(graph, subs_main_blend,
  918. subs_glow_combine, slink_c_src);
  919. } else
  920. m_graph.append_edge_attr(graph, msaa ? subs_res_opaque : subs_main_opaque,
  921. subs_glow_combine, slink_c_src);
  922. // not needed for combine postprocessing but simplifies keeping graph integrity
  923. // so it's always possible to get DEPTH-DEPTH link from it
  924. var subs_depth_in = sc_render.glow_over_blend ? subs_main_blend : subs_main_opaque;
  925. m_graph.append_edge_attr(graph, subs_depth_in, subs_glow_combine, slink_depth_o);
  926. var slink_c_y = create_slink("COLOR", "u_glow_mask_small", 1, 0.5, 0.5, true);
  927. slink_c_y.min_filter = m_tex.TF_LINEAR;
  928. slink_c_y.mag_filter = m_tex.TF_LINEAR;
  929. m_graph.append_edge_attr(graph, blur_y, subs_glow_combine, slink_c_y);
  930. var slink_c_y2 = create_slink("COLOR", "u_glow_mask_large", 1, 0.25, 0.25, true);
  931. slink_c_y2.min_filter = m_tex.TF_LINEAR;
  932. slink_c_y2.mag_filter = m_tex.TF_LINEAR;
  933. m_graph.append_edge_attr(graph, blur_y2, subs_glow_combine, slink_c_y2);
  934. prev_level = [subs_glow_combine];
  935. curr_level = [];
  936. }
  937. if (!sc_render.glow_over_blend) {
  938. var subs_main_blend = create_custom_sub_main(m_subs.MAIN_BLEND);
  939. curr_level.push(subs_main_blend);
  940. prev_level = curr_level;
  941. curr_level = [];
  942. }
  943. // debug view stuff: wireframe, clustering
  944. if (cfg_def.debug_view) {
  945. var cam = m_cam.clone_camera(main_cam, true);
  946. cam_scene_data.cameras.push(cam);
  947. var subs_debug_view = m_subs.create_subs_debug_view(cam);
  948. curr_level.push(subs_debug_view);
  949. m_graph.append_node_attr(graph, subs_debug_view);
  950. m_graph.append_edge_attr(graph, prev_level[0], subs_debug_view,
  951. slink_color_o);
  952. m_graph.append_edge_attr(graph, prev_level[0], subs_debug_view,
  953. slink_depth_o);
  954. if (subs_grass_map) {
  955. m_graph.append_edge_attr(graph, subs_grass_map, subs_debug_view,
  956. slink_grass_map_d);
  957. m_graph.append_edge_attr(graph, subs_grass_map, subs_debug_view,
  958. slink_grass_map_c);
  959. }
  960. m_debug.set_debug_view_subs(subs_debug_view);
  961. prev_level = curr_level;
  962. curr_level = [];
  963. }
  964. if (msaa) {
  965. var subs_res_geom = m_subs.create_subs_resolve();
  966. m_graph.append_node_attr(graph, subs_res_geom);
  967. curr_level.push(subs_res_geom);
  968. m_graph.append_edge_attr(graph, prev_level[0], subs_res_geom, slink_resolve_in_c);
  969. m_graph.append_edge_attr(graph, prev_level[0], subs_res_geom, slink_resolve_in_d);
  970. prev_level = curr_level;
  971. curr_level = [];
  972. }
  973. // last level of geometry rendering
  974. var last_geom_level = prev_level.slice(0);
  975. // prepare anchor visibility subscene
  976. if (!rtt && sc_render.anchor_visibility) {
  977. var cam = m_cam.clone_camera(main_cam, true);
  978. cam_scene_data.cameras.push(cam);
  979. // NOTE: possible bugs due to texture reuse
  980. var subs_anchor = m_subs.create_subs_anchor_visibility(cam);
  981. m_graph.append_node_attr(graph, subs_anchor);
  982. m_graph.append_edge_attr(graph, prev_level[0], subs_anchor,
  983. msaa ? slink_depth_resolve_o : slink_depth_o);
  984. }
  985. // god rays stuff
  986. if (god_rays && depth_tex && !rtt) {
  987. var max_ray_length = gr_params.max_ray_length;
  988. var intensity = gr_params.intensity;
  989. var steps_per_pass = gr_params.steps_per_pass;
  990. var subs_prev = prev_level[0];
  991. var water = water_params ? true : false;
  992. var slink_gr_d = create_slink("DEPTH", "u_input", 1, 1, 1, true);
  993. var slink_gr_c = create_slink("COLOR", "u_input", 1, 0.25, 0.25, true);
  994. slink_gr_c.min_filter = m_tex.TF_LINEAR;
  995. slink_gr_c.mag_filter = m_tex.TF_LINEAR;
  996. // 1-st pass
  997. var step = max_ray_length / steps_per_pass;
  998. var cam_god_rays = m_cam.clone_camera(main_cam, true);
  999. cam_scene_data.cameras.push(cam_god_rays);
  1000. var subs_god_rays = m_subs.create_subs_god_rays(cam_god_rays,
  1001. water, max_ray_length, true, step, num_lights,
  1002. steps_per_pass);
  1003. m_graph.append_node_attr(graph, subs_god_rays);
  1004. m_graph.append_edge_attr(graph, subs_prev, subs_god_rays, slink_gr_d);
  1005. // 2-nd pass
  1006. step = max_ray_length / steps_per_pass * 0.5;
  1007. var cam_blur1 = m_cam.clone_camera(main_cam, true);
  1008. cam_scene_data.cameras.push(cam_blur1);
  1009. var subs_gr_blur1 = m_subs.create_subs_god_rays(cam_blur1,
  1010. water, max_ray_length, false, step, num_lights,
  1011. steps_per_pass);
  1012. m_graph.append_node_attr(graph, subs_gr_blur1);
  1013. m_graph.append_edge_attr(graph, subs_god_rays, subs_gr_blur1, slink_gr_c);
  1014. // 3-d pass
  1015. step = max_ray_length / steps_per_pass * 0.25;
  1016. var cam_blur2 = m_cam.clone_camera(main_cam, true);
  1017. cam_scene_data.cameras.push(cam_blur2);
  1018. var subs_gr_blur2 = m_subs.create_subs_god_rays(cam_blur2,
  1019. water, max_ray_length, false, step, num_lights,
  1020. steps_per_pass);
  1021. m_graph.append_node_attr(graph, subs_gr_blur2);
  1022. m_graph.append_edge_attr(graph, subs_gr_blur1, subs_gr_blur2, slink_gr_c);
  1023. // combine with main scene
  1024. var subs_god_rays_comb = m_subs.create_subs_god_rays_comb(intensity,
  1025. num_lights);
  1026. curr_level.push(subs_god_rays_comb);
  1027. m_graph.append_node_attr(graph, subs_god_rays_comb);
  1028. m_graph.append_edge_attr(graph, subs_prev, subs_god_rays_comb,
  1029. create_slink("COLOR", "u_main", 1, 1, 1, true));
  1030. m_graph.append_edge_attr(graph, subs_gr_blur2, subs_god_rays_comb,
  1031. create_slink("COLOR", "u_god_rays", 1, 1, 1, true));
  1032. prev_level = curr_level;
  1033. curr_level = [];
  1034. }
  1035. // bloom
  1036. if (bloom_params && !rtt) {
  1037. var subs_prev = prev_level[0];
  1038. var subs_luminance = m_subs.create_subs_luminance();
  1039. m_graph.append_node_attr(graph, subs_luminance);
  1040. m_graph.append_edge_attr(graph, subs_prev, subs_luminance,
  1041. create_slink("COLOR", "u_input", 1, 1, 1, true));
  1042. var subs_av_luminance = m_subs.create_subs_av_luminance();
  1043. m_graph.append_node_attr(graph, subs_av_luminance);
  1044. // NOTE: deprecated
  1045. subs_av_luminance.camera.width = cfg_def.edge_min_tex_size_hack? 2: 1;
  1046. subs_av_luminance.camera.height = cfg_def.edge_min_tex_size_hack? 2: 1;
  1047. var slink_luminance_av = create_slink("COLOR", "u_input", 1, 0.25, 0.25, true);
  1048. slink_luminance_av.min_filter = m_tex.TF_LINEAR;
  1049. slink_luminance_av.mag_filter = m_tex.TF_LINEAR;
  1050. var slink_luminance_tr = create_slink("COLOR", "u_luminance", 1, 0.25, 0.25, true);
  1051. slink_luminance_tr.min_filter = m_tex.TF_LINEAR;
  1052. slink_luminance_tr.mag_filter = m_tex.TF_LINEAR;
  1053. m_graph.append_edge_attr(graph, subs_luminance, subs_av_luminance,
  1054. slink_luminance_av);
  1055. var bloom_key = bloom_params.key;
  1056. var edge_lum = bloom_params.edge_lum;
  1057. var cam_luminance = m_cam.clone_camera(main_cam, true);
  1058. cam_scene_data.cameras.push(cam_luminance);
  1059. var subs_lum_trunced = m_subs.create_subs_luminance_trunced(bloom_key,
  1060. edge_lum, num_lights, cam_luminance);
  1061. m_graph.append_node_attr(graph, subs_lum_trunced);
  1062. m_graph.append_edge_attr(graph, subs_prev, subs_lum_trunced,
  1063. create_slink("COLOR", "u_main", 1, 1, 1, true));
  1064. m_graph.append_edge_attr(graph, subs_luminance, subs_lum_trunced,
  1065. slink_luminance_tr);
  1066. m_graph.append_edge_attr(graph, subs_av_luminance, subs_lum_trunced,
  1067. create_slink("COLOR", "u_average_lum", 1, 1, 1, false));
  1068. var slink_blur_in = create_slink("COLOR", "u_color", 1, 0.25, 0.25, true);
  1069. slink_blur_in.min_filter = m_tex.TF_LINEAR;
  1070. slink_blur_in.mag_filter = m_tex.TF_LINEAR;
  1071. var blur_x = m_subs.create_subs_bloom_blur(graph, subs_luminance, "X_BLUR", true);
  1072. m_graph.append_node_attr(graph, blur_x);
  1073. m_graph.append_edge_attr(graph, subs_lum_trunced, blur_x, slink_blur_in);
  1074. var blur_y = m_subs.create_subs_bloom_blur(graph, blur_x, "Y_BLUR", true);
  1075. m_graph.append_node_attr(graph, blur_y);
  1076. m_graph.append_edge_attr(graph, blur_x, blur_y, slink_blur_in);
  1077. var bloom_blur = bloom_params.blur;
  1078. var subs_bloom_combine = m_subs.create_subs_bloom_combine(bloom_blur);
  1079. m_graph.append_node_attr(graph, subs_bloom_combine);
  1080. var slink_bloom = create_slink("COLOR", "u_bloom", 1, 0.25, 0.25, true);
  1081. slink_bloom.min_filter = m_tex.TF_LINEAR;
  1082. slink_bloom.mag_filter = m_tex.TF_LINEAR;
  1083. m_graph.append_edge_attr(graph, blur_y, subs_bloom_combine, slink_bloom);
  1084. m_graph.append_edge_attr(graph, subs_prev, subs_bloom_combine,
  1085. create_slink("COLOR", "u_main", 1, 1, 1, true));
  1086. curr_level.push(subs_bloom_combine);
  1087. prev_level = curr_level;
  1088. curr_level = [];
  1089. }
  1090. // depth of field stuff
  1091. if (dof && depth_tex && !rtt) {
  1092. var subs_prev = prev_level[0];
  1093. var cam_dof = m_cam.clone_camera(main_cam, true);
  1094. cam_scene_data.cameras.push(cam_dof);
  1095. if (cam_render.dof_bokeh) {
  1096. var slink_coc_in = create_slink("COLOR", "u_color", 1, 1, 1, true);
  1097. slink_coc_in.min_filter = m_tex.TF_LINEAR;
  1098. slink_coc_in.mag_filter = m_tex.TF_LINEAR;
  1099. var slink_coc_depth_in = create_slink("DEPTH", "u_depth", 1, 1, 1, true)
  1100. var slink_coc_out = create_slink("COLOR", "u_color", 1, 0.5, 0.5, true);
  1101. slink_coc_out.min_filter = m_tex.TF_NEAREST;
  1102. slink_coc_out.mag_filter = m_tex.TF_NEAREST;
  1103. var slink_blur_in = create_slink("COLOR", "u_color", 1, 0.5, 0.5, true);
  1104. slink_blur_in.min_filter = m_tex.TF_NEAREST;
  1105. slink_blur_in.mag_filter = m_tex.TF_NEAREST;
  1106. var slink_dof_blurred_in1 = create_slink("COLOR", "u_blurred1", 1, 0.5, 0.5, true)
  1107. slink_dof_blurred_in1.min_filter = m_tex.TF_LINEAR;
  1108. slink_dof_blurred_in1.mag_filter = m_tex.TF_LINEAR;
  1109. var slink_dof_blurred_in2 = create_slink("COLOR", "u_blurred2", 1, 0.5, 0.5, true)
  1110. slink_dof_blurred_in2.min_filter = m_tex.TF_LINEAR;
  1111. slink_dof_blurred_in2.mag_filter = m_tex.TF_LINEAR;
  1112. var subs_coc_in = last_geom_level[0];
  1113. if (cam_render.dof_foreground_blur) {
  1114. var cam_coc_fg = m_cam.clone_camera(main_cam, true);
  1115. cam_scene_data.cameras.push(cam_coc_fg);
  1116. var coc_fg = m_subs.create_subs_coc(cam_coc_fg, "COC_FOREGROUND");
  1117. cam_coc_fg.dof_distance = cam_render.dof_distance;
  1118. cam_coc_fg.dof_object = cam_render.dof_object;
  1119. cam_coc_fg.dof_front_start = cam_render.dof_front_start;
  1120. cam_coc_fg.dof_front_end = cam_render.dof_front_end;
  1121. cam_coc_fg.dof_rear_start = cam_render.dof_rear_start;
  1122. cam_coc_fg.dof_rear_end = cam_render.dof_rear_end;
  1123. cam_coc_fg.dof_power = cam_render.dof_power;
  1124. cam_coc_fg.dof_bokeh = cam_render.dof_bokeh;
  1125. cam_coc_fg.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1126. cam_coc_fg.dof_foreground_blur = cam_render.dof_foreground_blur;
  1127. cam_coc_fg.dof_on = true;
  1128. m_graph.append_node_attr(graph, coc_fg);
  1129. m_graph.append_edge_attr(graph, subs_prev, coc_fg, slink_coc_in);
  1130. m_graph.append_edge_attr(graph, subs_coc_in, coc_fg, slink_coc_depth_in);
  1131. var pp_alpha_x = m_subs.create_subs_postprocessing("X_ALPHA_BLUR");
  1132. m_graph.append_node_attr(graph, pp_alpha_x);
  1133. m_graph.append_edge_attr(graph, coc_fg, pp_alpha_x, slink_coc_out);
  1134. var pp_alpha_y = m_subs.create_subs_postprocessing("Y_ALPHA_BLUR");
  1135. m_graph.append_node_attr(graph, pp_alpha_y);
  1136. m_graph.append_edge_attr(graph, pp_alpha_x, pp_alpha_y, slink_blur_in);
  1137. var cam_coc = m_cam.clone_camera(main_cam, true);
  1138. var coc = m_subs.create_subs_coc(cam_coc, "COC_COMBINE");
  1139. cam_scene_data.cameras.push(cam_coc);
  1140. cam_coc.dof_distance = cam_render.dof_distance;
  1141. cam_coc.dof_object = cam_render.dof_object;
  1142. cam_coc.dof_front_start = cam_render.dof_front_start;
  1143. cam_coc.dof_front_end = cam_render.dof_front_end;
  1144. cam_coc.dof_rear_start = cam_render.dof_rear_start;
  1145. cam_coc.dof_rear_end = cam_render.dof_rear_end;
  1146. cam_coc.dof_power = cam_render.dof_power;
  1147. cam_coc.dof_bokeh = cam_render.dof_bokeh;
  1148. cam_coc.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1149. cam_coc.dof_foreground_blur = cam_render.dof_foreground_blur;
  1150. cam_coc.dof_on = true;
  1151. m_graph.append_node_attr(graph, coc);
  1152. m_graph.append_edge_attr(graph, subs_prev, coc, slink_coc_in);
  1153. m_graph.append_edge_attr(graph, subs_coc_in, coc, slink_coc_depth_in);
  1154. m_graph.append_edge_attr(graph, pp_alpha_y, coc,
  1155. create_slink("COLOR", "u_coc_fg", 1, 0.5, 0.5, true));
  1156. } else {
  1157. var cam_coc = m_cam.clone_camera(main_cam, true);
  1158. cam_scene_data.cameras.push(cam_coc);
  1159. var coc = m_subs.create_subs_coc(cam_coc, "COC_ALL");
  1160. cam_coc.dof_distance = cam_render.dof_distance;
  1161. cam_coc.dof_object = cam_render.dof_object;
  1162. cam_coc.dof_front_start = cam_render.dof_front_start;
  1163. cam_coc.dof_front_end = cam_render.dof_front_end;
  1164. cam_coc.dof_rear_start = cam_render.dof_rear_start;
  1165. cam_coc.dof_rear_end = cam_render.dof_rear_end;
  1166. cam_coc.dof_power = cam_render.dof_power;
  1167. cam_coc.dof_bokeh = cam_render.dof_bokeh;
  1168. cam_coc.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1169. cam_coc.dof_foreground_blur = cam_render.dof_foreground_blur;
  1170. cam_coc.dof_on = true;
  1171. m_graph.append_node_attr(graph, coc);
  1172. m_graph.append_edge_attr(graph, subs_prev, coc, slink_coc_in);
  1173. m_graph.append_edge_attr(graph, subs_coc_in, coc, slink_coc_depth_in);
  1174. }
  1175. var pp_x = m_subs.create_subs_postprocessing("X_DOF_BLUR");
  1176. pp_x.camera.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1177. m_graph.append_node_attr(graph, pp_x);
  1178. m_graph.append_edge_attr(graph, coc, pp_x, slink_coc_out);
  1179. var pp_y1 = m_subs.create_subs_postprocessing("Y_DOF_BLUR");
  1180. pp_y1.camera.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1181. m_graph.append_node_attr(graph, pp_y1);
  1182. m_graph.append_edge_attr(graph, pp_x, pp_y1, slink_blur_in);
  1183. var pp_y2 = m_subs.create_subs_postprocessing("Y_DOF_BLUR");
  1184. pp_y2.camera.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1185. m_graph.append_node_attr(graph, pp_y2);
  1186. m_graph.append_edge_attr(graph, pp_x, pp_y2, slink_blur_in);
  1187. var subs_dof = m_subs.create_subs_dof(cam_dof);
  1188. cam_dof.dof_distance = cam_render.dof_distance;
  1189. cam_dof.dof_object = cam_render.dof_object;
  1190. cam_dof.dof_front_start = cam_render.dof_front_start;
  1191. cam_dof.dof_front_end = cam_render.dof_front_end;
  1192. cam_dof.dof_rear_start = cam_render.dof_rear_start;
  1193. cam_dof.dof_rear_end = cam_render.dof_rear_end;
  1194. cam_dof.dof_power = cam_render.dof_power;
  1195. cam_dof.dof_bokeh = cam_render.dof_bokeh;
  1196. cam_dof.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1197. cam_dof.dof_foreground_blur = cam_render.dof_foreground_blur;
  1198. cam_dof.dof_on = true;
  1199. curr_level.push(subs_dof);
  1200. m_graph.append_node_attr(graph, subs_dof);
  1201. m_graph.append_edge_attr(graph, subs_prev, subs_dof,
  1202. create_slink("COLOR", "u_sharp", 1, 1, 1, true));
  1203. m_graph.append_edge_attr(graph, pp_y1, subs_dof, slink_dof_blurred_in1);
  1204. m_graph.append_edge_attr(graph, pp_y2, subs_dof, slink_dof_blurred_in2);
  1205. } else {
  1206. var slink_blur_x_in = create_slink("COLOR", "u_color", 1, 1, 1, true);
  1207. slink_blur_x_in.min_filter = m_tex.TF_LINEAR;
  1208. slink_blur_x_in.mag_filter = m_tex.TF_LINEAR;
  1209. var slink_blur_y_in = create_slink("COLOR", "u_color", 1, 1, 1, true);
  1210. slink_blur_y_in.min_filter = m_tex.TF_LINEAR;
  1211. slink_blur_y_in.mag_filter = m_tex.TF_LINEAR;
  1212. var pp_x = m_subs.create_subs_postprocessing("X_BLUR");
  1213. m_graph.append_node_attr(graph, pp_x);
  1214. m_graph.append_edge_attr(graph, subs_prev, pp_x, slink_blur_x_in);
  1215. var pp_y = m_subs.create_subs_postprocessing("Y_BLUR");
  1216. m_graph.append_node_attr(graph, pp_y);
  1217. m_graph.append_edge_attr(graph, pp_x, pp_y, slink_blur_y_in);
  1218. var subs_dof_in = last_geom_level[0];
  1219. var subs_dof = m_subs.create_subs_dof(cam_dof);
  1220. cam_dof.dof_distance = cam_render.dof_distance;
  1221. cam_dof.dof_object = cam_render.dof_object;
  1222. cam_dof.dof_front_start = cam_render.dof_front_start;
  1223. cam_dof.dof_front_end = cam_render.dof_front_end;
  1224. cam_dof.dof_rear_start = cam_render.dof_rear_start;
  1225. cam_dof.dof_rear_end = cam_render.dof_rear_end;
  1226. cam_dof.dof_power = cam_render.dof_power;
  1227. cam_dof.dof_bokeh = cam_render.dof_bokeh;
  1228. cam_dof.dof_bokeh_intensity = cam_render.dof_bokeh_intensity;
  1229. cam_dof.dof_foreground_blur = cam_render.dof_foreground_blur;
  1230. cam_dof.dof_on = true;
  1231. curr_level.push(subs_dof);
  1232. m_graph.append_node_attr(graph, subs_dof);
  1233. m_graph.append_edge_attr(graph, subs_prev, subs_dof,
  1234. create_slink("COLOR", "u_sharp", 1, 1, 1, true));
  1235. m_graph.append_edge_attr(graph, pp_y, subs_dof,
  1236. create_slink("COLOR", "u_blurred", 1, 1, 1, true));
  1237. m_graph.append_edge_attr(graph, subs_dof_in, subs_dof,
  1238. create_slink("DEPTH", "u_depth", 1, 1, 1, true));
  1239. }
  1240. prev_level = curr_level;
  1241. curr_level = [];
  1242. }
  1243. // objects which are rendered above all
  1244. if (sc_render.xray) {
  1245. var subs_main_xray = create_custom_sub_main(m_subs.MAIN_XRAY);
  1246. curr_level.push(subs_main_xray);
  1247. prev_level = curr_level;
  1248. curr_level = [];
  1249. }
  1250. // motion blur stuff
  1251. if (motion_blur && !rtt) {
  1252. var subs_to_blur = prev_level[0];
  1253. var subs_mb = m_subs.create_subs_motion_blur(mb_params.mb_decay_threshold,
  1254. mb_params.mb_factor);
  1255. curr_level.push(subs_mb);
  1256. m_graph.append_node_attr(graph, subs_mb);
  1257. var slink_mb_in = create_slink("COLOR", "u_mb_tex_curr", 1, 1, 1, true);
  1258. m_graph.append_edge_attr(graph, subs_to_blur, subs_mb, slink_mb_in);
  1259. var slink_mb_accum = create_slink("COLOR", "u_mb_tex_accum", 1, 1, 1, true);
  1260. subs_mb.slinks_internal.push(slink_mb_accum);
  1261. prev_level = curr_level;
  1262. curr_level = [];
  1263. }
  1264. // outline_mask
  1265. if (!rtt && sc_render.outline) {
  1266. var subs_prev = prev_level[0];
  1267. var cam_outline = m_cam.clone_camera(main_cam, true);
  1268. cam_scene_data.cameras.push(cam_outline);
  1269. var subs_outline_mask = m_subs.create_subs_outline_mask(cam_outline, num_lights);
  1270. m_graph.append_node_attr(graph, subs_outline_mask);
  1271. var pp_x_ext = m_subs.create_subs_postprocessing("X_EXTEND");
  1272. // almost the same
  1273. var slink_mask_pp = create_slink("COLOR", "u_color", 1, 1, 1, true);
  1274. var slink_mask_gl = create_slink("COLOR", "u_outline_mask", 1, 1, 1, true);
  1275. pp_x_ext.is_for_outline = true;
  1276. m_graph.append_node_attr(graph, pp_x_ext);
  1277. m_graph.append_edge_attr(graph, subs_outline_mask, pp_x_ext,
  1278. slink_mask_pp);
  1279. var slink_ext = create_slink("COLOR", "u_color", 1, 0.5, 0.5, true);
  1280. slink_ext.min_filter = m_tex.TF_LINEAR;
  1281. slink_ext.mag_filter = m_tex.TF_LINEAR;
  1282. var pp_y_ext = m_subs.create_subs_postprocessing("Y_EXTEND");
  1283. pp_y_ext.is_for_outline = true;
  1284. m_graph.append_node_attr(graph, pp_y_ext);
  1285. m_graph.append_edge_attr(graph, pp_x_ext, pp_y_ext, slink_ext);
  1286. var pp_x = m_subs.create_subs_postprocessing("X_BLUR");
  1287. pp_x.is_for_outline = true;
  1288. m_graph.append_node_attr(graph, pp_x);
  1289. m_graph.append_edge_attr(graph, pp_y_ext, pp_x, slink_ext);
  1290. // almost the same
  1291. var slink_blur_blur = create_slink("COLOR", "u_color", 1, 0.25, 0.25, true);
  1292. slink_blur_blur.min_filter = m_tex.TF_LINEAR;
  1293. slink_blur_blur.mag_filter = m_tex.TF_LINEAR;
  1294. var slink_blur_outline = create_slink("COLOR", "u_outline_mask_blurred", 1, 0.25, 0.25, true);
  1295. slink_blur_outline.min_filter = m_tex.TF_LINEAR;
  1296. slink_blur_outline.mag_filter = m_tex.TF_LINEAR;
  1297. var pp_y = m_subs.create_subs_postprocessing("Y_BLUR");
  1298. pp_y.is_for_outline = true;
  1299. m_graph.append_node_attr(graph, pp_y);
  1300. m_graph.append_edge_attr(graph, pp_x, pp_y, slink_blur_blur);
  1301. var subs_outline = m_subs.create_subs_outline(outline_params);
  1302. m_graph.append_node_attr(graph, subs_outline);
  1303. m_graph.append_edge_attr(graph, subs_prev, subs_outline,
  1304. create_slink("COLOR", "u_outline_src", 1, 1, 1, true));
  1305. m_graph.append_edge_attr(graph, subs_outline_mask, subs_outline,
  1306. slink_mask_gl);
  1307. m_graph.append_edge_attr(graph, pp_y, subs_outline, slink_blur_outline);
  1308. curr_level.push(subs_outline);
  1309. prev_level = curr_level;
  1310. curr_level = [];
  1311. }
  1312. enforce_slink_uniqueness(graph, depth_tex);
  1313. if ((sc_render.anaglyph_use || sc_render.hmd_stereo_use) && !rtt) {
  1314. var subs_stereo = make_stereo(graph, sc_render, cam_scene_data, prev_level[0]);
  1315. curr_level.push(subs_stereo);
  1316. prev_level = curr_level;
  1317. curr_level = [];
  1318. }
  1319. // compositing
  1320. if (compositing && !rtt) {
  1321. var subs_prev = prev_level[0];
  1322. var brightness = cc_params.brightness;
  1323. var contrast = cc_params.contrast;
  1324. var exposure = cc_params.exposure;
  1325. var saturation = cc_params.saturation;
  1326. var subs_compositing = m_subs.create_subs_compositing(brightness, contrast,
  1327. exposure, saturation);
  1328. m_graph.append_node_attr(graph, subs_compositing);
  1329. m_graph.append_edge_attr(graph, subs_prev, subs_compositing,
  1330. create_slink("COLOR", "u_color", 1, 1, 1, true));
  1331. curr_level.push(subs_compositing);
  1332. prev_level = curr_level;
  1333. curr_level = [];
  1334. }
  1335. // antialiasing stuff
  1336. if (antialiasing) {
  1337. var subs_prev = prev_level[0];
  1338. if (cfg_def.smaa) {
  1339. var slink_smaa_in = create_slink("COLOR", "u_color",
  1340. 1, 1, 1, true);
  1341. slink_smaa_in.min_filter = m_tex.TF_LINEAR;
  1342. slink_smaa_in.mag_filter = m_tex.TF_LINEAR;
  1343. // NOTE: temoporary disabled T2X mode due to artifacts with blend objects
  1344. //if (!m_cfg.context.alpha) {
  1345. // var depth_subs = find_upper_subs(graph, subs_prev, "DEPTH");
  1346. // // velocity buffer
  1347. // var cam_velocity = m_cam.clone_camera(main_cam, true);
  1348. // cam_scene_data.cameras.push(cam_velocity);
  1349. // var subs_velocity = m_subs.create_subs_veloctity(cam_velocity);
  1350. // var slink_velocity_in = create_slink("DEPTH", "u_depth",
  1351. // 1, 1, 1, true);
  1352. // slink_velocity_in.min_filter = m_tex.TF_NEAREST;
  1353. // slink_velocity_in.mag_filter = m_tex.TF_NEAREST;
  1354. // m_graph.append_node_attr(graph, subs_velocity);
  1355. // m_graph.append_edge_attr(graph, depth_subs, subs_velocity,
  1356. // slink_velocity_in);
  1357. // var slink_velocity_smaa = create_slink("COLOR", "u_velocity_tex",
  1358. // 1, 1, 1, true);
  1359. //}
  1360. // 1-st pass - edge detection
  1361. var subs_smaa_1 = m_subs.create_subs_smaa(m_subs.SMAA_EDGE_DETECTION, sc_render);
  1362. m_graph.append_node_attr(graph, subs_smaa_1);
  1363. m_graph.append_edge_attr(graph, subs_prev, subs_smaa_1,
  1364. slink_smaa_in);
  1365. // 2-nd pass - blending weight calculation
  1366. var subs_smaa_2 = m_subs.create_subs_smaa(m_subs.SMAA_BLENDING_WEIGHT_CALCULATION, sc_render);
  1367. m_graph.append_node_attr(graph, subs_smaa_2);
  1368. m_graph.append_edge_attr(graph, subs_smaa_1, subs_smaa_2,
  1369. slink_smaa_in);
  1370. var slink_search_tex = create_slink("COLOR", "u_search_tex",
  1371. 1, 1, 1, false);
  1372. var slink_area_tex = create_slink("COLOR", "u_area_tex",
  1373. 1, 1, 1, false);
  1374. slink_search_tex.min_filter = m_tex.TF_LINEAR;
  1375. slink_search_tex.mag_filter = m_tex.TF_LINEAR;
  1376. slink_area_tex.min_filter = m_tex.TF_LINEAR;
  1377. slink_area_tex.mag_filter = m_tex.TF_LINEAR;
  1378. subs_smaa_2.slinks_internal.push(slink_search_tex);
  1379. subs_smaa_2.slinks_internal.push(slink_area_tex);
  1380. // 3-rd pass - neighborhood blending
  1381. var subs_smaa_3 = m_subs.create_subs_smaa(m_subs.SMAA_NEIGHBORHOOD_BLENDING, sc_render);
  1382. m_graph.append_node_attr(graph, subs_smaa_3);
  1383. m_graph.append_edge_attr(graph, subs_prev,
  1384. subs_smaa_3, slink_smaa_in);
  1385. var slink_smaa_blend = create_slink("COLOR", "u_blend",
  1386. 1, 1, 1, true);
  1387. slink_smaa_blend.min_filter = m_tex.TF_LINEAR;
  1388. slink_smaa_blend.mag_filter = m_tex.TF_LINEAR;
  1389. m_graph.append_edge_attr(graph, subs_smaa_2,
  1390. subs_smaa_3, slink_smaa_blend);
  1391. // 4-th pass - resolve
  1392. // NOTE: temoporary disabled T2X mode due to artifacts with blend objects
  1393. //if (!m_cfg.context.alpha) {
  1394. // m_graph.append_edge_attr(graph, subs_velocity, subs_smaa_3,
  1395. // slink_velocity_smaa);
  1396. // var subs_smaa_r = m_subs.create_subs_smaa(m_subs.SMAA_RESOLVE, sc_render);
  1397. // m_graph.append_node_attr(graph, subs_smaa_r);
  1398. // m_graph.append_edge_attr(graph, subs_smaa_3, subs_smaa_r,
  1399. // slink_smaa_in);
  1400. // m_graph.append_edge_attr(graph, subs_velocity, subs_smaa_r,
  1401. // slink_velocity_smaa);
  1402. // var slink_smaa_in_prev = create_slink("COLOR", "u_color_prev",
  1403. // 1, 1, 1, true);
  1404. // slink_smaa_in_prev.min_filter = m_tex.TF_LINEAR;
  1405. // slink_smaa_in_prev.mag_filter = m_tex.TF_LINEAR;
  1406. // subs_smaa_r.slinks_internal.push(slink_smaa_in_prev);
  1407. // curr_level.push(subs_smaa_r);
  1408. //} else
  1409. curr_level.push(subs_smaa_3);
  1410. } else {
  1411. var subs_aa = m_subs.create_subs_aa(sc_render);
  1412. m_graph.append_node_attr(graph, subs_aa);
  1413. var slink_aa_in = create_slink("COLOR", "u_color", 1, 1, 1, true);
  1414. slink_aa_in.min_filter = m_tex.TF_LINEAR;
  1415. slink_aa_in.mag_filter = m_tex.TF_LINEAR;
  1416. m_graph.append_edge_attr(graph, subs_prev, subs_aa, slink_aa_in);
  1417. curr_level.push(subs_aa);
  1418. }
  1419. prev_level = curr_level;
  1420. curr_level = [];
  1421. }
  1422. // special precautions needed to prevent subscenes with through-going
  1423. // attachments from on-screen or RTT (!!!) rendering
  1424. // NOTE: it's not possible to resolve (blit) directly on screen framebuffer
  1425. // NOTE: may be a Chromium bug
  1426. var prev_id = m_graph.node_by_attr(graph, prev_level[0]);
  1427. if (prev_level[0].type == m_subs.MOTION_BLUR ||
  1428. prev_level[0].type == m_subs.RESOLVE)
  1429. var need_subs_pp_copy = true;
  1430. else {
  1431. var need_subs_pp_copy = false;
  1432. m_graph.traverse_inputs(graph, prev_id, function(id_in, attr_in,
  1433. attr_edge) {
  1434. var slink_in = attr_edge;
  1435. if (slink_in.from == slink_in.to) {
  1436. need_subs_pp_copy = true;
  1437. return true;
  1438. }
  1439. });
  1440. }
  1441. if (need_subs_pp_copy) {
  1442. var subs_pp_copy = m_subs.create_subs_postprocessing("NONE");
  1443. m_graph.append_node_attr(graph, subs_pp_copy);
  1444. m_graph.append_edge_attr(graph, prev_level[0], subs_pp_copy,
  1445. create_slink("COLOR", "u_color", 1, 1, 1, true));
  1446. curr_level.push(subs_pp_copy);
  1447. prev_level = curr_level;
  1448. curr_level = [];
  1449. }
  1450. // NOTE: from anaglyph
  1451. curr_level.push(prev_level[0]);
  1452. //
  1453. // filling up the last level
  1454. //
  1455. if (subs_color_picking)
  1456. if (subs_color_picking_xray)
  1457. curr_level.push(subs_color_picking_xray);
  1458. else
  1459. curr_level.push(subs_color_picking);
  1460. if (subs_anchor)
  1461. curr_level.push(subs_anchor);
  1462. var tex_size = cfg_scs.cubemap_tex_size;
  1463. if (sc_render.sky_params.render_sky) {
  1464. var sky_params = sc_render.sky_params;
  1465. var wls = sc_render.world_light_set;
  1466. var tex_param = wls.sky_texture_param;
  1467. tex_size = tex_param ? tex_param.tex_size : tex_size;
  1468. var subs_sky = m_subs.create_subs_sky(wls, num_lights, sky_params, tex_size);
  1469. m_graph.append_node_attr(graph, subs_sky);
  1470. curr_level.push(subs_sky);
  1471. }
  1472. var subs_sink = m_subs.create_subs_sink();
  1473. m_graph.append_node_attr(graph, subs_sink);
  1474. for (var i = 0; i < curr_level.length; i++) {
  1475. var subs = curr_level[i];
  1476. switch (subs.type) {
  1477. case m_subs.COLOR_PICKING:
  1478. case m_subs.COLOR_PICKING_XRAY:
  1479. m_graph.append_edge_attr(graph, subs, subs_sink,
  1480. create_slink("COLOR", "NONE", 1, 1, 1, false));
  1481. m_graph.append_edge_attr(graph, subs, subs_sink,
  1482. create_slink("DEPTH", "NONE", 1, 1, 1, false));
  1483. break;
  1484. case m_subs.SKY:
  1485. var slink_sky = create_slink("CUBEMAP", "u_sky",
  1486. tex_size, 1, 1, false);
  1487. m_graph.append_edge_attr(graph, subs, subs_sink, slink_sky);
  1488. break;
  1489. case m_subs.ANCHOR_VISIBILITY:
  1490. var slink_anchor_color = create_slink("COLOR", "NONE", 1, 1, 1, true);
  1491. m_graph.append_edge_attr(graph, subs, subs_sink, slink_anchor_color);
  1492. break;
  1493. default:
  1494. if (rtt) {
  1495. var tex0 = render_to_textures[0];
  1496. var slink_rtt = create_slink("COLOR", "OFFSCREEN", 1, 1, 1, true);
  1497. slink_rtt.texture = tex0;
  1498. // first one connected directly to SINK
  1499. m_graph.append_edge_attr(graph, curr_level[i], subs_sink, slink_rtt);
  1500. for (var j = 1; j < render_to_textures.length; j++) {
  1501. var tex = render_to_textures[j];
  1502. var subs_scale = m_subs.create_subs_postprocessing("NONE");
  1503. m_graph.append_node_attr(graph, subs_scale);
  1504. var slink_to_rtt = create_slink("COLOR", "SCALE", 1, 1, 1, true);
  1505. m_graph.append_edge_attr(graph, curr_level[i], subs_scale,
  1506. slink_to_rtt);
  1507. // copied textures have smaller size
  1508. var size_mult = tex.source_size / tex0.source_size;
  1509. var slink_rtt = create_slink("COLOR", "OFFSCREEN", 1,
  1510. size_mult, size_mult, true);
  1511. slink_rtt.texture = tex;
  1512. m_graph.append_edge_attr(graph, subs_scale, subs_sink, slink_rtt);
  1513. }
  1514. } else
  1515. m_graph.append_edge_attr(graph, curr_level[i], subs_sink,
  1516. create_slink("SCREEN", "NONE", 1, 1, 1, true));
  1517. break;
  1518. }
  1519. }
  1520. // remove unconnected opaque resolve node
  1521. if (subs_res_opaque && !get_outputs(graph, subs_res_opaque).length) {
  1522. m_graph.remove_node(graph,
  1523. m_graph.node_by_attr(graph, subs_res_opaque));
  1524. m_graph.cleanup_loose_edges(graph);
  1525. }
  1526. enforce_slink_uniqueness(graph, depth_tex);
  1527. enforce_graph_consistency(graph, depth_tex);
  1528. if (cfg_dbg.enabled) {
  1529. var subs_from = find_debug_subs(graph);
  1530. if (subs_from)
  1531. assign_debug_subscene(graph, subs_from);
  1532. }
  1533. process_subscene_links(graph);
  1534. assign_render_targets(graph);
  1535. if (shadow_params) {
  1536. m_graph.traverse(graph, function(nid, subs) {
  1537. if (subs.type == m_subs.SHADOW_RECEIVE ||
  1538. subs.type == m_subs.MAIN_BLEND ||
  1539. subs.type == m_subs.MAIN_XRAY)
  1540. prepare_shadow_receive_subs(graph, subs);
  1541. });
  1542. }
  1543. return graph;
  1544. }
  1545. function find_debug_subs(graph) {
  1546. var subs_dbg = null;
  1547. var subs_num = 0;
  1548. m_graph.traverse(graph, function(id, attr) {
  1549. if (attr.type == cfg_dbg.subs_type) {
  1550. if (subs_num == cfg_dbg.subs_number) {
  1551. subs_dbg = attr;
  1552. return true;
  1553. } else
  1554. subs_num++;
  1555. }
  1556. });
  1557. return subs_dbg;
  1558. }
  1559. function assign_debug_subscene(graph, subs_to_debug) {
  1560. var node_to_debug = m_graph.node_by_attr(graph, subs_to_debug);
  1561. var subs_debug_view = m_subs.create_subs_postprocessing("NONE");
  1562. var node_debug_view = m_graph.append_node_attr(graph, subs_debug_view);
  1563. var node_sink = m_graph.get_sink_nodes(graph)[0];
  1564. m_graph.traverse_edges(graph, function(edge_from, edge_to, edge_attr) {
  1565. if (edge_to == node_sink) {
  1566. m_graph.reconnect_edges(graph, edge_from, node_sink, edge_from, node_debug_view);
  1567. }
  1568. });
  1569. var has_multisample = subs_check_multisample(subs_to_debug, graph);
  1570. m_graph.traverse_edges(graph, function(edge_from, edge_to, edge_attr) {
  1571. if (edge_from == node_to_debug) {
  1572. if (has_multisample) {
  1573. var subs_res_geom = m_subs.create_subs_resolve();
  1574. m_graph.append_node_attr(graph, subs_res_geom);
  1575. var slink_resolve_in_c = create_slink("COLOR", "RESOLVE", 1, 1, 1, true);
  1576. slink_resolve_in_c.multisample = true;
  1577. slink_resolve_in_c.use_renderbuffer = true;
  1578. var slink_resolve_in_d = create_slink("DEPTH", "RESOLVE", 1, 1, 1, true);
  1579. slink_resolve_in_d.multisample = true;
  1580. slink_resolve_in_d.use_renderbuffer = true;
  1581. m_graph.append_edge_attr(graph, subs_to_debug, subs_res_geom, slink_resolve_in_c);
  1582. m_graph.append_edge_attr(graph, subs_to_debug, subs_res_geom, slink_resolve_in_d);
  1583. subs_to_debug = subs_res_geom;
  1584. }
  1585. m_graph.append_edge_attr(graph, subs_to_debug, subs_debug_view,
  1586. create_slink(cfg_dbg.slink_type, "u_color", edge_attr.size,
  1587. edge_attr.size_mult_x, edge_attr.size_mult_y,
  1588. edge_attr.update_dim));
  1589. return true;
  1590. }
  1591. });
  1592. m_graph.append_edge(graph, node_debug_view, node_sink,
  1593. create_slink("SCREEN", "NONE", 0.5, 0.5, 0.5, true));
  1594. }
  1595. function subs_check_multisample(subs, graph) {
  1596. var has_multisample = false;
  1597. var node = m_graph.node_by_attr(graph, subs);
  1598. // node without output edges has not multisampling
  1599. if (m_graph.out_edge_count(graph, node)) {
  1600. var node_out = m_graph.get_out_edge(graph, node, 0);
  1601. var edge_attr = m_graph.get_edge_attr(graph, node, node_out, 0);
  1602. if (edge_attr.from == "COLOR" && edge_attr.to == "COLOR"
  1603. || edge_attr.from == "DEPTH" && edge_attr.to == "DEPTH") {
  1604. var attr_out = m_graph.get_node_attr(graph, node_out);
  1605. has_multisample = subs_check_multisample(attr_out, graph);
  1606. } else
  1607. has_multisample = edge_attr.to == "RESOLVE";
  1608. }
  1609. return has_multisample;
  1610. }
  1611. function make_stereo(graph, sc_render, cam_scene_data, prev_subs) {
  1612. var cams = cam_scene_data.cameras;
  1613. var antialiasing = sc_render.antialiasing;
  1614. var hmd_stereo_use = sc_render.hmd_stereo_use;
  1615. var plane_refl_subs = sc_render.reflection_params.plane_refl_subs;
  1616. var plane_refl_subs_blend = sc_render.reflection_params.plane_refl_subs_blend;
  1617. var nid_pre_sink = m_graph.get_node_id(graph, prev_subs);
  1618. var subs_pre_sink = prev_subs;
  1619. var subgraph_right = m_graph.subgraph_node_conn(graph, nid_pre_sink,
  1620. m_graph.BACKWARD_DIR);
  1621. // [[original left only subscene, new right subscene, original slink]...]
  1622. var left_only_edges = [];
  1623. var removed_subscenes = [];
  1624. var source_nodes_right = [];
  1625. var subs_clone_cb = function(subs) {
  1626. var subs_new;
  1627. // shared
  1628. if (LEFT_ONLY_SUBS_TYPES.indexOf(subs.type) > -1) {
  1629. removed_subscenes.push(subs);
  1630. subs_new = subs;
  1631. } else {
  1632. subs_new = m_subs.clone_subs(subs);
  1633. if (subs_new.type == m_subs.MAIN_PLANE_REFLECT) {
  1634. // NOTE: x[0] --- left eye
  1635. for (var i = 0; i < plane_refl_subs.length; i++) {
  1636. if (plane_refl_subs[i][0] == subs) {
  1637. plane_refl_subs[i] = [subs, subs_new];
  1638. subs_new.camera.reflection_plane = subs.camera.reflection_plane;
  1639. cam_scene_data.cameras.push(subs_new.camera);
  1640. break;
  1641. }
  1642. }
  1643. }
  1644. // just copy camera from opaque scene for blend reflection
  1645. if (subs.type == m_subs.MAIN_PLANE_REFLECT_BLEND) {
  1646. // NOTE: x[0] --- left eye
  1647. for (var i = 0; i < plane_refl_subs.length; i++) {
  1648. if (plane_refl_subs_blend[i][0] == subs) {
  1649. plane_refl_subs_blend[i] = [subs, subs_new];
  1650. subs_new.camera = plane_refl_subs[i][1].camera;
  1651. break;
  1652. }
  1653. }
  1654. } else if (cams.indexOf(subs.camera) > -1) {
  1655. if (hmd_stereo_use) {
  1656. m_cam.make_stereo(subs.camera, m_cam.TYPE_HMD_LEFT);
  1657. m_cam.make_stereo(subs_new.camera, m_cam.TYPE_HMD_RIGHT);
  1658. } else {
  1659. m_cam.make_stereo(subs.camera, m_cam.TYPE_STEREO_LEFT);
  1660. m_cam.make_stereo(subs_new.camera, m_cam.TYPE_STEREO_RIGHT);
  1661. }
  1662. cams.push(subs_new.camera);
  1663. }
  1664. var nid_subs = m_graph.node_by_attr(graph, subs);
  1665. m_graph.traverse_inputs(graph, nid_subs, function(nid_in, subs_in,
  1666. slink) {
  1667. if (LEFT_ONLY_SUBS_TYPES.indexOf(subs_in.type) > -1)
  1668. left_only_edges.push([subs_in, subs_new, slink]);
  1669. });
  1670. if (subs.type !== m_subs.MOTION_BLUR)
  1671. for (var i = 0; i < subs.slinks_internal.length; i++)
  1672. subs_new.slinks_internal[i].parent_slink = subs.slinks_internal[i];
  1673. // render order: store source nodes for right eye
  1674. var is_source_node = true;
  1675. for (var i = 0; i < m_graph.in_edge_count(graph, nid_subs); i++) {
  1676. var nid_upper_subs = m_graph.get_in_edge(graph, nid_subs, i);
  1677. var upper_subs = m_graph.get_node_attr(graph, nid_upper_subs);
  1678. if (LEFT_ONLY_SUBS_TYPES.indexOf(upper_subs.type) == -1)
  1679. is_source_node = false;
  1680. }
  1681. if (is_source_node)
  1682. source_nodes_right.push(subs_new);
  1683. }
  1684. return subs_new;
  1685. }
  1686. var slink_clone_cb = function(slink) {
  1687. var new_slink = clone_slink(slink, true);
  1688. new_slink.parent_slink = slink;
  1689. return new_slink;
  1690. }
  1691. subgraph_right = m_graph.clone(subgraph_right, subs_clone_cb, slink_clone_cb);
  1692. m_graph.traverse_edges(subgraph_right, function(node1, node2, slink) {
  1693. var subs = m_graph.get_node_attr(subgraph_right, node1);
  1694. if (subs.type === m_subs.MOTION_BLUR)
  1695. slink.parent_slink = null;
  1696. });
  1697. for (var i = 0; i < removed_subscenes.length; i++)
  1698. m_graph.remove_node(subgraph_right,
  1699. m_graph.node_by_attr(subgraph_right, removed_subscenes[i]));
  1700. m_graph.cleanup_loose_edges(subgraph_right);
  1701. var subs_stereo = m_subs.create_subs_stereo(hmd_stereo_use);
  1702. var nid_stereo = m_graph.append_node_attr(graph, subs_stereo);
  1703. // HACK: fix subs texture reusage of last left subs
  1704. var left_clone = m_subs.create_subs_copy();
  1705. m_graph.append_node_attr(graph, left_clone);
  1706. var slink_left_copy = create_slink("COLOR", "COPY", 1, 1, 1, true);
  1707. m_graph.append_edge_attr(graph, subs_pre_sink, left_clone, slink_left_copy);
  1708. var slink_left = create_slink("COLOR", "u_sampler_left", 1, 1, 1, true);
  1709. slink_left.unique_texture = true;
  1710. slink_left.min_filter = m_tex.TF_LINEAR;
  1711. slink_left.mag_filter = m_tex.TF_LINEAR;
  1712. m_graph.append_edge_attr(graph, left_clone, subs_stereo, slink_left);
  1713. if (!subs_pre_sink.is_pp) {
  1714. var right_clone = m_subs.create_subs_copy();
  1715. m_graph.append_node_attr(subgraph_right, right_clone);
  1716. var slink_right_copy = create_slink("COLOR", "COPY", 1, 1, 1, true);
  1717. slink_right_copy.parent_slink = slink_left_copy;
  1718. var nid_right_sink = m_graph.get_sink_nodes(subgraph_right)[0];
  1719. var right_sink = m_graph.get_node_attr(subgraph_right, nid_right_sink);
  1720. m_graph.append_edge_attr(subgraph_right, right_sink, right_clone, slink_right_copy);
  1721. }
  1722. var slink_right = create_slink("COLOR", "u_sampler_right", 1, 1, 1, true);
  1723. slink_right.min_filter = m_tex.TF_LINEAR;
  1724. slink_right.mag_filter = m_tex.TF_LINEAR;
  1725. m_graph.append_subgraph(subgraph_right, graph,
  1726. [m_graph.get_sink_nodes(subgraph_right)[0], nid_stereo,
  1727. slink_right]
  1728. );
  1729. for (var i = 0; i < left_only_edges.length; i++) {
  1730. var subs1 = left_only_edges[i][0];
  1731. var subs2 = left_only_edges[i][1];
  1732. var slink = left_only_edges[i][2];
  1733. m_graph.append_edge_attr(graph, subs1, subs2, slink);
  1734. }
  1735. // render order: left eye before right eye
  1736. var slink_order = create_slink("SCREEN", "NONE", 0, 0, 0, false);
  1737. for (var i = 0; i < source_nodes_right.length; i++)
  1738. m_graph.append_edge_attr(graph, left_clone, source_nodes_right[i], slink_order);
  1739. // resize subs texture for hmd
  1740. if (hmd_stereo_use)
  1741. multiply_size_mult_by_graph(graph, 0.5, 1);
  1742. return subs_stereo;
  1743. }
  1744. exports.multiply_size_mult_by_graph = multiply_size_mult_by_graph;
  1745. function multiply_size_mult_by_graph(graph, multiplier_x, multiplier_y) {
  1746. var slink_list = [];
  1747. m_graph.traverse(graph, function(subs_id, subs) {
  1748. if (LEFT_ONLY_SUBS_TYPES.indexOf(subs.type) == -1 &&
  1749. subs.slinks_internal.length &&
  1750. has_lower_subs(graph, subs, m_subs.STEREO)) {
  1751. for (var i = 0; i < subs.slinks_internal.length; i++) {
  1752. var slink = subs.slinks_internal[i];
  1753. if (slink_list.indexOf(slink) == -1)
  1754. slink_list.push(slink);
  1755. }
  1756. }
  1757. });
  1758. m_graph.traverse_edges(graph, function(node1, node2, slink) {
  1759. var subs1 = m_graph.get_node_attr(graph, node1);
  1760. var subs2 = m_graph.get_node_attr(graph, node2);
  1761. if (LEFT_ONLY_SUBS_TYPES.indexOf(subs1.type) == -1 &&
  1762. has_lower_subs(graph, subs2, m_subs.STEREO)) {
  1763. if (slink_list.indexOf(slink) == -1)
  1764. slink_list.push(slink);
  1765. }
  1766. });
  1767. for (var i = 0; i < slink_list.length; i++) {
  1768. slink_list[i].size_mult_x *= multiplier_x;
  1769. slink_list[i].size_mult_y *= multiplier_y;
  1770. }
  1771. }
  1772. /**
  1773. * Set subs texel size
  1774. */
  1775. exports.set_texel_size = set_texel_size;
  1776. function set_texel_size(subs, size_x, size_y) {
  1777. var mult = subs.texel_size_multiplier;
  1778. subs.texel_size[0] = size_x * subs.texel_mask[0] * mult;
  1779. subs.texel_size[1] = size_y * subs.texel_mask[1] * mult;
  1780. }
  1781. /**
  1782. * Set subs texel size multiplier.
  1783. * Use set_texel_size() to update shader uniforms
  1784. */
  1785. exports.set_texel_size_mult = set_texel_size_mult;
  1786. function set_texel_size_mult(subs, mult) {
  1787. subs.texel_size_multiplier = mult;
  1788. }
  1789. function create_slink(from, to, size, size_mult_x, size_mult_y, update_dim) {
  1790. var slink = {
  1791. // assign explicitly in all cases
  1792. from: from,
  1793. to: to,
  1794. size: size,
  1795. size_mult_x: size_mult_x,
  1796. size_mult_y: size_mult_y,
  1797. update_dim: update_dim,
  1798. // generic default values
  1799. active: true,
  1800. texture: null,
  1801. multisample: false,
  1802. use_renderbuffer: false,
  1803. min_filter: m_tex.TF_NEAREST,
  1804. mag_filter: m_tex.TF_NEAREST,
  1805. unique_texture: false,
  1806. use_comparison: false
  1807. };
  1808. return slink;
  1809. }
  1810. function clone_slink(slink, tex_by_link) {
  1811. if (tex_by_link) {
  1812. var tex = slink.texture;
  1813. slink.texture = null;
  1814. }
  1815. if (slink.texture)
  1816. m_util.panic("Failed to clone slink with attached texture");
  1817. var slink_new = m_util.clone_object_json(slink);
  1818. if (tex_by_link) {
  1819. slink.texture = tex;
  1820. slink_new.texture = tex;
  1821. }
  1822. return slink_new;
  1823. }
  1824. function prepare_shadow_receive_subs(graph, subs) {
  1825. var csm_index = 0;
  1826. var subs_inputs = get_inputs(graph, subs);
  1827. var v_light_tsr_num = 0;
  1828. for (var i = 0; i < subs_inputs.length; i++) {
  1829. var input = subs_inputs[i];
  1830. // shadow map with optional blurring
  1831. if (input.type == m_subs.SHADOW_CAST) {
  1832. v_light_tsr_num++;
  1833. subs.p_light_matrix = subs.p_light_matrix || new Array();
  1834. var index = input.shadow_lamp_index > 0 ? input.shadow_lamp_index : csm_index;
  1835. // assign uniforms from cast camera by link
  1836. subs.p_light_matrix[index] = input.camera.proj_matrix;
  1837. csm_index++;
  1838. }
  1839. }
  1840. if (!subs.v_light_ts || !subs.v_light_r) {
  1841. if (cfg_def.mac_os_shadow_hack)
  1842. subs.v_light_tsr = new Float32Array(v_light_tsr_num * 9);
  1843. else {
  1844. subs.v_light_ts = new Float32Array(v_light_tsr_num * 4);
  1845. subs.v_light_r = new Float32Array(v_light_tsr_num * 4);
  1846. }
  1847. }
  1848. }
  1849. exports.create_performance_graph = function() {
  1850. var graph = m_graph.create();
  1851. var subs_perf = m_subs.create_subs_perf();
  1852. var cam = m_cam.create_camera(m_cam.TYPE_NONE);
  1853. var size = 512;
  1854. cam.width = size;
  1855. cam.height = size;
  1856. subs_perf.camera = cam;
  1857. m_graph.append_node_attr(graph, subs_perf);
  1858. subs_perf.slinks_internal.push(create_slink("COLOR",
  1859. "u_color", size, 1, 1, false));
  1860. var subs_sink = m_subs.create_subs_sink();
  1861. m_graph.append_node_attr(graph, subs_sink);
  1862. m_graph.append_edge_attr(graph, subs_perf, subs_sink,
  1863. create_slink("COLOR", "NONE", size, 1, 1, false));
  1864. // create_slink("SCREEN", "NONE", size, 1, 1, false));
  1865. process_subscene_links(graph);
  1866. assign_render_targets(graph);
  1867. return graph;
  1868. }
  1869. /**
  1870. * Find first on-screen subscene.
  1871. */
  1872. exports.find_on_screen = function(graph) {
  1873. var subs = null;
  1874. m_graph.traverse(graph, function(node, attr) {
  1875. if (attr.camera && attr.camera.framebuffer === null) {
  1876. subs = attr;
  1877. return true;
  1878. }
  1879. return false;
  1880. });
  1881. return subs;
  1882. }
  1883. /**
  1884. * Find input of given type.
  1885. */
  1886. exports.find_input = function(graph, subs, type) {
  1887. var inputs = get_inputs(graph, subs);
  1888. for (var i = 0; i < inputs.length; i++)
  1889. if (inputs[i].type == type)
  1890. return inputs[i];
  1891. return null;
  1892. }
  1893. /**
  1894. * Get inputs of given type.
  1895. */
  1896. exports.get_inputs_by_type = function(graph, subs, type) {
  1897. var inputs = get_inputs(graph, subs);
  1898. var matching_inputs = [];
  1899. for (var i = 0; i < inputs.length; i++)
  1900. if (inputs[i].type == type)
  1901. matching_inputs.push(inputs[i]);
  1902. return matching_inputs;
  1903. }
  1904. exports.has_lower_subs = has_lower_subs;
  1905. /**
  1906. * Traverse graph downwards and check if subs has output of given type.
  1907. * subs itself also checked
  1908. * @methodOf graph
  1909. */
  1910. function has_lower_subs(graph, subs, type) {
  1911. if (subs.type == type)
  1912. return true;
  1913. var outputs = get_outputs(graph, subs);
  1914. for (var i = 0; i < outputs.length; i++)
  1915. if (has_lower_subs(graph, outputs[i], type))
  1916. return true;
  1917. return false;
  1918. }
  1919. exports.has_upper_subs = has_upper_subs;
  1920. /**
  1921. * Traverse graph upwards and check if subs has input of given type.
  1922. * subs itself also checked
  1923. * @methodOf graph
  1924. */
  1925. function has_upper_subs(graph, subs, type) {
  1926. if (subs.type == type)
  1927. return true;
  1928. var inputs = get_inputs(graph, subs);
  1929. for (var i = 0; i < inputs.length; i++)
  1930. if (has_upper_subs(graph, inputs[i], type))
  1931. return true;
  1932. return false;
  1933. }
  1934. /**
  1935. * Traverse graph upwards and find first subscene of given type.
  1936. * subs itself also may be found,
  1937. * @methodOf graph
  1938. */
  1939. function find_upper_subs(graph, subs, type) {
  1940. if (subs.type == type)
  1941. return subs;
  1942. var inputs = get_inputs(graph, subs);
  1943. for (var i = 0; i < inputs.length; i++) {
  1944. var upper = find_upper_subs(graph, inputs[i], type);
  1945. if (upper)
  1946. return upper;
  1947. }
  1948. return null;
  1949. }
  1950. exports.get_inputs = get_inputs;
  1951. function get_inputs(graph, subs) {
  1952. var node = m_graph.node_by_attr(graph, subs);
  1953. if (node == m_graph.NULL_NODE)
  1954. m_util.panic("Subscene not in graph");
  1955. var inputs = [];
  1956. var in_edge_count = m_graph.in_edge_count(graph, node);
  1957. for (var i = 0; i < in_edge_count; i++) {
  1958. var node_input = m_graph.get_in_edge(graph, node, i);
  1959. if (node_input != node)
  1960. inputs.push(m_graph.get_node_attr(graph, node_input));
  1961. }
  1962. return inputs;
  1963. }
  1964. exports.get_outputs = get_outputs;
  1965. function get_outputs(graph, subs) {
  1966. var node = m_graph.node_by_attr(graph, subs);
  1967. if (node == m_graph.NULL_NODE)
  1968. m_util.panic("Subscene not in graph");
  1969. var outputs = [];
  1970. var out_edge_count = m_graph.out_edge_count(graph, node);
  1971. for (var i = 0; i < out_edge_count; i++) {
  1972. var node_output = m_graph.get_out_edge(graph, node, i);
  1973. if (node_output != node)
  1974. outputs.push(m_graph.get_node_attr(graph, node_output));
  1975. }
  1976. return outputs;
  1977. }
  1978. /**
  1979. * Find first subscene in graph/array matching given type
  1980. */
  1981. exports.find_subs = function(graph, type) {
  1982. var subs = null;
  1983. m_graph.traverse(graph, function(node, attr) {
  1984. if (attr.type == type) {
  1985. subs = attr;
  1986. return true;
  1987. }
  1988. return false;
  1989. });
  1990. return subs;
  1991. }
  1992. exports.debug_convert_to_dot = function(graph) {
  1993. var PAPER_SIZE = "11.7,16.5"; // A3
  1994. //var PAPER_SIZE = "8.3,11.7"; // A4
  1995. var dot_str = "digraph scenegraph {\n";
  1996. dot_str += " ";
  1997. dot_str += "size=\"" + PAPER_SIZE + "\";\n";
  1998. dot_str += " ";
  1999. dot_str += "ratio=\"fill\";\n";
  2000. dot_str += " ";
  2001. dot_str += "node [shape=box margin=\"0.25,0.055\"];\n"
  2002. var tex_ids = debug_calc_tex_ids(graph);
  2003. m_graph.traverse(graph, function(node, attr) {
  2004. dot_str += " ";
  2005. dot_str += dot_format_node(node, attr, tex_ids);
  2006. });
  2007. m_graph.traverse_edges(graph, function(node1, node2, attr) {
  2008. dot_str += " ";
  2009. dot_str += dot_format_edge(node1, node2, attr, tex_ids);
  2010. });
  2011. dot_str += "}";
  2012. return dot_str;
  2013. }
  2014. function debug_calc_tex_ids(graph) {
  2015. var index_buf = [];
  2016. var ids = [];
  2017. traverse_slinks(graph, function(slink, internal, subs1, subs2) {
  2018. if (slink.texture) {
  2019. var num = index_buf.indexOf(slink.texture);
  2020. if (num == -1) {
  2021. index_buf.push(slink.texture);
  2022. ids.push(slink.texture, index_buf.length - 1);
  2023. }
  2024. }
  2025. });
  2026. return ids;
  2027. }
  2028. function dot_format_node(node, subs, tex_ids) {
  2029. var cam = subs.camera;
  2030. var label = m_subs.subs_label(subs);
  2031. if (subs.camera) {
  2032. label += "\\n"
  2033. for (var i = 0; i < tex_ids.length; i+=2) {
  2034. var c_att = subs.camera.color_attachment;
  2035. if (tex_ids[i] == c_att) {
  2036. if (m_tex.is_renderbuffer(c_att))
  2037. label += "CR" + tex_ids[i+1] + " ";
  2038. else
  2039. label += "C" + tex_ids[i+1] + " ";
  2040. }
  2041. }
  2042. for (var i = 0; i < tex_ids.length; i+=2) {
  2043. var d_att = subs.camera.depth_attachment
  2044. if (tex_ids[i] == d_att) {
  2045. if (m_tex.is_renderbuffer(d_att))
  2046. label += "DR" + tex_ids[i+1];
  2047. else
  2048. label += "D" + tex_ids[i+1];
  2049. }
  2050. }
  2051. }
  2052. if (subs.slinks_internal.length)
  2053. label += "\\n-----\\n";
  2054. for (var i = 0; i < subs.slinks_internal.length; i++)
  2055. label += dot_format_edge_label(subs.slinks_internal[i], node, null,
  2056. tex_ids);
  2057. var color = "black";
  2058. if (subs.type == m_subs.SINK)
  2059. var style = "dotted";
  2060. else if (subs.enqueue)
  2061. var style = "solid";
  2062. else
  2063. var style = "dashed";
  2064. style += ",bold";
  2065. return String(node) + " [label=\"" + label + "\" " +
  2066. "color=\"" + color + "\" " +
  2067. "style=\"" + style + "\"" +
  2068. "];\n";
  2069. }
  2070. function dot_format_edge(node1, node2, slink, tex_ids) {
  2071. var label = dot_format_edge_label(slink, node1, node2, tex_ids);
  2072. if (slink.active)
  2073. var style = "solid";
  2074. else
  2075. var style = "dotted";
  2076. return String(node1) + " -> " + String(node2) + " [label=\"" + label + "\" " +
  2077. "style=\"" + style + "\"];\n";
  2078. }
  2079. function dot_format_edge_label(slink, node1, node2, tex_ids) {
  2080. function filters_to_string(filters) {
  2081. var string = "";
  2082. if (filters.min == m_tex.TF_LINEAR)
  2083. string += "L";
  2084. else if (filters.min == m_tex.TF_NEAREST)
  2085. string += "N";
  2086. if (filters.mag == m_tex.TF_LINEAR)
  2087. string += "L";
  2088. else if (filters.mag == m_tex.TF_NEAREST)
  2089. string += "N";
  2090. return string;
  2091. };
  2092. var label = "";
  2093. label += slink.from + "\\n"
  2094. label += slink.to != "NONE" ? slink.to + "\\n" : "";
  2095. label += "("
  2096. if (slink.update_dim) {
  2097. var size_mult_x = slink.size_mult_x;
  2098. var size_mult_y = slink.size_mult_y;
  2099. if (Math.round(size_mult_x) != size_mult_x)
  2100. size_mult_x = size_mult_x.toFixed(2);
  2101. if (Math.round(size_mult_y) != size_mult_y)
  2102. size_mult_y = size_mult_y.toFixed(2);
  2103. var size_x = (size_mult_x == 1 ? "" : size_mult_x) + "S";
  2104. var size_y = (size_mult_y == 1 ? "" : size_mult_y) + "S";
  2105. label += size_x + "x" + size_y;
  2106. } else {
  2107. var size_mult_x = slink.size_mult_x;
  2108. var size_mult_y = slink.size_mult_y;
  2109. label += slink.size * size_mult_x + "x" + slink.size * size_mult_y;
  2110. }
  2111. if (slink.from != "SCREEN") {
  2112. label += " ";
  2113. // texture filtering
  2114. if (slink.use_renderbuffer)
  2115. label += "RR";
  2116. else
  2117. label += filters_to_string({min: slink.min_filter, mag: slink.mag_filter});
  2118. // texture ID number (sharing info)
  2119. for (var i = 0; i < tex_ids.length; i+=2) {
  2120. if (tex_ids[i] == slink.texture)
  2121. label += " " + tex_ids[i+1];
  2122. }
  2123. }
  2124. label += ")" + "\\n"
  2125. return label;
  2126. }
  2127. /**
  2128. * Create new rendering queue based on graph structure.
  2129. * Perform topological sorting based on depth-first search algorithm.
  2130. * @param graph Rendering graph array
  2131. * @param [subs_sink] Root subscene node
  2132. */
  2133. exports.create_rendering_queue = function(graph) {
  2134. var subscenes = m_graph.topsort_attr(graph);
  2135. var queue = [];
  2136. for (var i = 0; i < subscenes.length; i++) {
  2137. var subs = subscenes[i];
  2138. if (subs.enqueue)
  2139. queue.push(subs);
  2140. }
  2141. return queue;
  2142. }
  2143. }