Pass.hx 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. package h3d.mat;
  2. import h3d.mat.Data;
  3. @:allow(h3d.mat.BaseMaterial)
  4. #if !macro
  5. @:build(hxd.impl.BitsBuilder.build())
  6. #end
  7. class Pass {
  8. public var name(default, null) : String;
  9. var flags : Int;
  10. var passId : Int;
  11. var bits : Int = 0;
  12. var parentPass : Pass;
  13. var parentShaders : hxsl.ShaderList;
  14. var selfShaders(default, null) : hxsl.ShaderList;
  15. var selfShadersChanged(default, null) : Bool;
  16. var selfShadersCache : hxsl.ShaderList;
  17. var shaders : hxsl.ShaderList;
  18. var nextPass : Pass;
  19. var rendererFlags : Int = 0;
  20. @:bits(flags) public var enableLights : Bool;
  21. /**
  22. Inform the pass system that the parameters will be modified in object draw() command,
  23. so they will be manually uploaded by calling RenderContext.uploadParams.
  24. **/
  25. @:bits(flags) public var dynamicParameters : Bool;
  26. /**
  27. Mark the pass as static, this will allow some renderers or shadows to filter it
  28. when rendering static/dynamic parts.
  29. **/
  30. @:bits(flags) public var isStatic : Bool;
  31. @:bits(flags) var batchMode : Bool; // for MeshBatch
  32. @:bits(bits) public var culling : Face;
  33. @:bits(bits) public var depthWrite : Bool;
  34. @:bits(bits) public var depthTest : Compare;
  35. @:bits(bits) public var blendSrc : Blend;
  36. @:bits(bits) public var blendDst : Blend;
  37. @:bits(bits) public var blendAlphaSrc : Blend;
  38. @:bits(bits) public var blendAlphaDst : Blend;
  39. @:bits(bits) public var blendOp : Operation;
  40. @:bits(bits) public var blendAlphaOp : Operation;
  41. @:bits(bits) public var wireframe : Bool;
  42. @:bits(bits) public var culled : Bool;
  43. public var colorMask : Int;
  44. public var layer : Int = 0;
  45. public var stencil : Stencil;
  46. // one bit for internal engine usage
  47. @:bits(bits) @:noCompletion var reserved : Bool;
  48. public function new(name, ?shaders, ?parent) {
  49. this.parentPass = parent;
  50. this.shaders = shaders;
  51. setPassName(name);
  52. culling = Back;
  53. blend(One, Zero);
  54. depth(true, Less);
  55. blendOp = blendAlphaOp = Add;
  56. colorMask = 15;
  57. }
  58. public function load( p : Pass ) {
  59. name = p.name;
  60. passId = p.passId;
  61. bits = p.bits;
  62. enableLights = p.enableLights;
  63. dynamicParameters = p.dynamicParameters;
  64. culling = p.culling;
  65. depthWrite = p.depthWrite;
  66. depthTest = p.depthTest;
  67. blendSrc = p.blendSrc;
  68. blendDst = p.blendDst;
  69. blendOp = p.blendOp;
  70. blendAlphaSrc = p.blendAlphaSrc;
  71. blendAlphaDst = p.blendAlphaDst;
  72. blendAlphaOp = p.blendAlphaOp;
  73. colorMask = p.colorMask;
  74. if (p.stencil != null) {
  75. if (stencil == null) stencil = new Stencil();
  76. stencil.load(p.stencil);
  77. }
  78. }
  79. public function setPassName( name : String ) {
  80. this.name = name;
  81. passId = hxsl.Globals.allocID(name);
  82. }
  83. public inline function blend( src, dst ) {
  84. this.blendSrc = src;
  85. this.blendAlphaSrc = src;
  86. this.blendDst = dst;
  87. this.blendAlphaDst = dst;
  88. }
  89. public function setBlendMode( b : BlendMode ) {
  90. blendOp = Add;
  91. blendAlphaOp = Add;
  92. switch( b ) {
  93. case None: // Out = 1 * Src + 0 * Dst
  94. blend(One, Zero);
  95. case Alpha: // Out = SrcA * Src + (1 - SrcA) * Dst
  96. blend(SrcAlpha, OneMinusSrcAlpha);
  97. blendAlphaSrc = One;
  98. case Add: // Out = SrcA * Src + 1 * Dst
  99. blend(SrcAlpha, One);
  100. blendAlphaSrc = One;
  101. case AlphaAdd: // Out = Src + (1 - SrcA) * Dst
  102. blend(One, OneMinusSrcAlpha);
  103. case SoftAdd: // Out = (1 - Dst) * Src + 1 * Dst
  104. blend(OneMinusDstColor, One);
  105. blendAlphaSrc = One;
  106. case Multiply: // Out = Dst * Src + 0 * Dst
  107. blend(DstColor, Zero);
  108. blendAlphaSrc = One;
  109. case AlphaMultiply: // Out = Dst * Src + (1 - SrcA) * Dst
  110. blend(DstColor, OneMinusSrcAlpha);
  111. case Erase: // Out = 0 * Src + (1 - Srb) * Dst
  112. blend(Zero, OneMinusSrcColor);
  113. case Screen: // Out = 1 * Src + (1 - Srb) * Dst
  114. blend(One, OneMinusSrcColor);
  115. case Sub: // Out = 1 * Dst - SrcA * Src
  116. blend(SrcAlpha, One);
  117. blendOp = ReverseSub;
  118. blendAlphaOp = ReverseSub;
  119. case Max: // Out = MAX( Src, Dst )
  120. blend(One, One);
  121. blendAlphaOp = Max;
  122. blendOp = Max;
  123. case Min: // Out = MIN( Src, Dst )
  124. blend(One, One);
  125. blendAlphaOp = Min;
  126. blendOp = Min;
  127. }
  128. }
  129. public function depth( write, test ) {
  130. this.depthWrite = write;
  131. this.depthTest = test;
  132. }
  133. public function setColorMask(r, g, b, a) {
  134. this.colorMask = (r?1:0) | (g?2:0) | (b?4:0) | (a?8:0);
  135. }
  136. public function setColorChannel( c : hxsl.Channel) {
  137. switch( c ) {
  138. case R: setColorMask(true, false, false, false);
  139. case G: setColorMask(false, true, false, false);
  140. case B: setColorMask(false, false, true, false);
  141. case A: setColorMask(false, false, false, true);
  142. default: throw "Unsupported channel "+c;
  143. }
  144. }
  145. public function setColorMaski(r, g, b, a, i) {
  146. if ( i > 8 )
  147. throw "Color mask i supports 8 Render target";
  148. var mask = (r?1:0) | (g?2:0) | (b?4:0) | (a?8:0);
  149. mask = mask << (i * 4);
  150. this.colorMask = this.colorMask | mask;
  151. }
  152. function resetRendererFlags() {
  153. rendererFlags = 0;
  154. }
  155. public function addShader<T:hxsl.Shader>(s:T) : T {
  156. // throwing an exception will require NG GameServer review
  157. if( s == null ) return null;
  158. shaders = hxsl.ShaderList.addSort(s, shaders);
  159. resetRendererFlags();
  160. return s;
  161. }
  162. function addSelfShader<T:hxsl.Shader>(s:T) : T {
  163. if ( s == null ) return null;
  164. selfShadersChanged = true;
  165. selfShaders = hxsl.ShaderList.addSort(s, selfShaders);
  166. resetRendererFlags();
  167. return s;
  168. }
  169. /**
  170. Can be used for internal usage
  171. **/
  172. function addShaderAtIndex<T:hxsl.Shader>(s:T, index:Int) : T {
  173. var prev = null;
  174. var cur = shaders;
  175. while( index > 0 && cur != parentShaders ) {
  176. prev = cur;
  177. cur = cur.next;
  178. index--;
  179. }
  180. if( prev == null )
  181. shaders = new hxsl.ShaderList(s, cur);
  182. else
  183. prev.next = new hxsl.ShaderList(s, cur);
  184. return s;
  185. }
  186. function getShaderIndex(s:hxsl.Shader) : Int {
  187. var index = 0;
  188. var cur = shaders;
  189. while( cur != parentShaders ) {
  190. if( cur.s == s ) return index;
  191. cur = cur.next;
  192. index++;
  193. }
  194. return -1;
  195. }
  196. public function removeShader(s) {
  197. var sl = shaders, prev = null;
  198. var shaderFound = false;
  199. while( sl != null ) {
  200. if( sl.s == s ) {
  201. resetRendererFlags();
  202. if ( selfShadersCache == sl )
  203. selfShadersCache = selfShadersCache.next;
  204. if( prev == null )
  205. shaders = sl.next;
  206. else
  207. prev.next = sl.next;
  208. shaderFound = true;
  209. break;
  210. }
  211. prev = sl;
  212. sl = sl.next;
  213. }
  214. sl = selfShaders;
  215. prev = null;
  216. while ( sl != null ) {
  217. if ( sl.s == s ) {
  218. resetRendererFlags();
  219. if ( selfShadersCache == sl )
  220. selfShadersCache = selfShadersCache.next;
  221. if ( prev == null )
  222. selfShaders = sl.next;
  223. else
  224. prev.next = sl.next;
  225. return true;
  226. }
  227. prev = sl;
  228. sl = sl.next;
  229. }
  230. return shaderFound;
  231. }
  232. public function removeShaders< T:hxsl.Shader >(t:Class<T>) {
  233. var sl = shaders;
  234. var prev = null;
  235. while( sl != null ) {
  236. if( Std.isOfType(sl.s, t) ) {
  237. resetRendererFlags();
  238. if ( selfShadersCache == sl )
  239. selfShadersCache = selfShadersCache.next;
  240. if( prev == null )
  241. shaders = sl.next;
  242. else
  243. prev.next = sl.next;
  244. }
  245. else
  246. prev = sl;
  247. sl = sl.next;
  248. }
  249. sl = selfShaders;
  250. prev = null;
  251. while( sl != null ) {
  252. if( Std.isOfType(sl.s, t) ) {
  253. resetRendererFlags();
  254. if ( selfShadersCache == sl )
  255. selfShadersCache = selfShadersCache.next;
  256. if( prev == null )
  257. selfShaders = sl.next;
  258. else
  259. prev.next = sl.next;
  260. }
  261. else
  262. prev = sl;
  263. sl = sl.next;
  264. }
  265. }
  266. public function getShader< T:hxsl.Shader >(t:Class<T>) : T {
  267. var s = _getShader(t, shaders);
  268. return s != null ? s : _getShader(t, selfShaders);
  269. }
  270. function _getShader< T:hxsl.Shader >(t:Class<T>, s : hxsl.ShaderList) : T {
  271. while( s != null && s != parentShaders ) {
  272. var sh = Std.downcast(s.s, t);
  273. if( sh != null )
  274. return sh;
  275. s = s.next;
  276. }
  277. return null;
  278. }
  279. public function getShaderByName( name : String ) : hxsl.Shader {
  280. var s = _getShaderByName(name, shaders);
  281. return s != null ? s : _getShaderByName(name, selfShaders);
  282. }
  283. function _getShaderByName( name : String, sl : hxsl.ShaderList ) : hxsl.Shader {
  284. while( sl != null && sl != parentShaders ) {
  285. if( @:privateAccess sl.s.shader.data.name == name )
  286. return sl.s;
  287. sl = sl.next;
  288. }
  289. return null;
  290. }
  291. public inline function getShaders() {
  292. return shaders.iterateTo(parentShaders);
  293. }
  294. function checkInfiniteLoop() {
  295. var shaderList = [];
  296. var s = selfShaders;
  297. while ( s != null ) {
  298. for ( already in shaderList )
  299. if ( already == s )
  300. throw "infinite loop";
  301. shaderList.push(s);
  302. s = s.next;
  303. }
  304. }
  305. function selfShadersRec(rebuild : Bool) {
  306. if ( selfShaders == null )
  307. return shaders;
  308. if ( !selfShadersChanged && !rebuild && shaders == selfShadersCache )
  309. return selfShaders;
  310. var sl = selfShaders, prev = null;
  311. while ( sl != null && sl != selfShadersCache ) {
  312. prev = sl;
  313. sl = sl.next;
  314. }
  315. selfShadersCache = shaders;
  316. if ( prev != null )
  317. prev.next = selfShadersCache;
  318. else
  319. selfShaders = shaders;
  320. return selfShaders;
  321. }
  322. function getShadersRec() {
  323. if( parentPass == null || parentShaders == parentPass.shaders ) {
  324. return selfShadersRec(false);
  325. }
  326. // relink to our parent shader list
  327. var s = shaders, prev = null;
  328. while( s != null && s != parentShaders ) {
  329. prev = s;
  330. s = s.next;
  331. }
  332. if ( s != parentShaders )
  333. prev = null;
  334. parentShaders = parentPass.shaders;
  335. if( prev == null )
  336. shaders = parentShaders;
  337. else
  338. prev.next = parentShaders;
  339. return selfShadersRec(true);
  340. }
  341. function reverseDepthTest() {
  342. depthTest = switch( depthTest ) {
  343. case Greater: Less;
  344. case GreaterEqual: LessEqual;
  345. case Less: Greater;
  346. case LessEqual: GreaterEqual;
  347. default: depthTest;
  348. };
  349. }
  350. public function clone() {
  351. var p = new Pass(name, shaders.clone());
  352. p.selfShaders = selfShaders;
  353. p.bits = bits;
  354. p.enableLights = enableLights;
  355. if (stencil != null) p.stencil = stencil.clone();
  356. return p;
  357. }
  358. }