babylon.modelRenderCache.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. module BABYLON {
  2. export const enum ShaderDataType {
  3. Vector2, Vector3, Vector4, float, Color3, Color4, Size
  4. }
  5. export class GroupInstanceInfo {
  6. constructor(owner: Group2D, mrc: ModelRenderCache, partCount: number) {
  7. this._partCount = partCount;
  8. this._primCount = 0;
  9. this.owner = owner;
  10. this.modelRenderCache = mrc;
  11. this.modelRenderCache.addRef();
  12. this.partIndexFromId = new StringDictionary<number>();
  13. this._usedShaderCategories = new Array<string>(partCount);
  14. this._strides = new Array<number>(partCount);
  15. this._opaqueData = null;
  16. this._alphaTestData = null;
  17. this._transparentData = null;
  18. this.opaqueDirty = this.alphaTestDirty = this.transparentDirty = this.transparentOrderDirty = false;
  19. }
  20. public incPrimCount() {
  21. ++this._primCount;
  22. }
  23. public dispose(): boolean {
  24. if (this._isDisposed) {
  25. return false;
  26. }
  27. // Disposed is called when a primitive instance is disposed, so we decrement the counter
  28. --this._primCount;
  29. // If the counter is still greater than 0 there's still other primitives using this GII
  30. if (this._primCount > 0) {
  31. return false;
  32. }
  33. // We're going to dispose this GII, first remove it from the dictionary
  34. this.owner._renderableData._renderGroupInstancesInfo.remove(this.modelRenderCache.modelKey);
  35. if (this.modelRenderCache) {
  36. this.modelRenderCache.dispose();
  37. this.modelRenderCache = null;
  38. }
  39. let engine = this.owner.owner.engine;
  40. if (this._opaqueData) {
  41. this._opaqueData.forEach(d => d.dispose(engine));
  42. this._opaqueData = null;
  43. }
  44. if (this._alphaTestData) {
  45. this._alphaTestData.forEach(d => d.dispose(engine));
  46. this._alphaTestData = null;
  47. }
  48. if (this._transparentData) {
  49. this._transparentData.forEach(d => d.dispose(engine));
  50. this._transparentData = null;
  51. }
  52. this.partIndexFromId = null;
  53. this._isDisposed = true;
  54. return true;
  55. }
  56. public get isDisposed(): boolean {
  57. return this._isDisposed;
  58. }
  59. private _isDisposed: boolean;
  60. owner: Group2D;
  61. modelRenderCache: ModelRenderCache;
  62. partIndexFromId: StringDictionary<number>;
  63. get hasOpaqueData(): boolean {
  64. return this._opaqueData != null;
  65. }
  66. get hasAlphaTestData(): boolean {
  67. return this._alphaTestData != null;
  68. }
  69. get hasTransparentData(): boolean {
  70. return this._transparentData != null;
  71. }
  72. opaqueDirty: boolean;
  73. get opaqueData(): GroupInfoPartData[] {
  74. if (!this._opaqueData) {
  75. this._opaqueData = new Array<GroupInfoPartData>(this._partCount);
  76. for (let i = 0; i < this._partCount; i++) {
  77. this._opaqueData[i] = new GroupInfoPartData(this._strides[i]);
  78. }
  79. }
  80. return this._opaqueData;
  81. }
  82. alphaTestDirty: boolean;
  83. get alphaTestData(): GroupInfoPartData[] {
  84. if (!this._alphaTestData) {
  85. this._alphaTestData = new Array<GroupInfoPartData>(this._partCount);
  86. for (let i = 0; i < this._partCount; i++) {
  87. this._alphaTestData[i] = new GroupInfoPartData(this._strides[i]);
  88. }
  89. }
  90. return this._alphaTestData;
  91. }
  92. transparentOrderDirty: boolean;
  93. transparentDirty: boolean;
  94. get transparentData(): TransparentGroupInfoPartData[] {
  95. if (!this._transparentData) {
  96. this._transparentData = new Array<TransparentGroupInfoPartData>(this._partCount);
  97. for (let i = 0; i < this._partCount; i++) {
  98. let zoff = this.modelRenderCache._partData[i]._zBiasOffset;
  99. this._transparentData[i] = new TransparentGroupInfoPartData(this._strides[i], zoff);
  100. }
  101. }
  102. return this._transparentData;
  103. }
  104. sortTransparentData() {
  105. if (!this.transparentOrderDirty) {
  106. return;
  107. }
  108. for (let i = 0; i < this._transparentData.length; i++) {
  109. let td = this._transparentData[i];
  110. td._partData.sort();
  111. }
  112. this.transparentOrderDirty = false;
  113. }
  114. get usedShaderCategories(): string[] {
  115. return this._usedShaderCategories;
  116. }
  117. get strides(): number[] {
  118. return this._strides;
  119. }
  120. private _partCount: number;
  121. private _primCount: number;
  122. private _strides: number[];
  123. private _usedShaderCategories: string[];
  124. private _opaqueData: GroupInfoPartData[];
  125. private _alphaTestData: GroupInfoPartData[];
  126. private _transparentData: TransparentGroupInfoPartData[];
  127. }
  128. export class TransparentSegment {
  129. constructor() {
  130. this.groupInsanceInfo = null;
  131. this.startZ = 0;
  132. this.endZ = 0;
  133. this.startDataIndex = Prim2DBase._bigInt;
  134. this.endDataIndex = 0;
  135. this.partBuffers = null;
  136. }
  137. dispose(engine: Engine) {
  138. if (this.partBuffers) {
  139. this.partBuffers.forEach(b => engine._releaseBuffer(b));
  140. this.partBuffers.splice(0);
  141. this.partBuffers = null;
  142. }
  143. }
  144. groupInsanceInfo: GroupInstanceInfo;
  145. startZ: number;
  146. endZ: number;
  147. startDataIndex: number;
  148. endDataIndex: number;
  149. partBuffers: WebGLBuffer[];
  150. }
  151. export class GroupInfoPartData {
  152. _partData: DynamicFloatArray = null;
  153. _partBuffer: WebGLBuffer = null;
  154. _partBufferSize: number = 0;
  155. constructor(stride: number) {
  156. this._partData = new DynamicFloatArray(stride/4, 50);
  157. this._isDisposed = false;
  158. }
  159. public dispose(engine: Engine): boolean {
  160. if (this._isDisposed) {
  161. return false;
  162. }
  163. if (this._partBuffer) {
  164. engine._releaseBuffer(this._partBuffer);
  165. this._partBuffer = null;
  166. }
  167. this._partData = null;
  168. this._isDisposed = true;
  169. }
  170. private _isDisposed: boolean;
  171. }
  172. export class TransparentGroupInfoPartData extends GroupInfoPartData {
  173. constructor(stride: number, zoff: number) {
  174. super(stride);
  175. this._partData.compareValueOffset = zoff;
  176. this._partData.sortingAscending = false;
  177. }
  178. }
  179. export class ModelRenderCache {
  180. constructor(engine: Engine, modelKey: string) {
  181. this._engine = engine;
  182. this._modelKey = modelKey;
  183. this._nextKey = 1;
  184. this._refCounter = 1;
  185. this._partData = null;
  186. }
  187. public dispose(): boolean {
  188. if (--this._refCounter !== 0) {
  189. return false;
  190. }
  191. // Remove the Model Render Cache from the global dictionary
  192. let edata = this._engine.getExternalData<Canvas2DEngineBoundData>("__BJSCANVAS2D__");
  193. if (edata) {
  194. edata.DisposeModelRenderCache(this);
  195. }
  196. return true;
  197. }
  198. public get isDisposed(): boolean {
  199. return this._refCounter <= 0;
  200. }
  201. public addRef(): number {
  202. return ++this._refCounter;
  203. }
  204. public get modelKey(): string {
  205. return this._modelKey;
  206. }
  207. public updateModelRenderCache(prim: Prim2DBase): boolean {
  208. return false;
  209. }
  210. /**
  211. * Render the model instances
  212. * @param instanceInfo
  213. * @param context
  214. * @return must return true is the rendering succeed, false if the rendering couldn't be done (asset's not yet ready, like Effect)
  215. */
  216. render(instanceInfo: GroupInstanceInfo, context: Render2DContext): boolean {
  217. return true;
  218. }
  219. protected getPartIndexFromId(partId: number) {
  220. for (var i = 0; i < this._partData.length; i++) {
  221. if (this._partData[i]._partId === partId) {
  222. return i;
  223. }
  224. }
  225. return null;
  226. }
  227. protected loadInstancingAttributes(partId: number, effect: Effect): InstancingAttributeInfo[] {
  228. let i = this.getPartIndexFromId(partId);
  229. if (i === null) {
  230. return null;
  231. }
  232. var ci = this._partsClassInfo[i];
  233. var categories = this._partData[i]._partUsedCategories;
  234. let res = ci.classContent.getInstancingAttributeInfos(effect, categories);
  235. return res;
  236. }
  237. //setupUniformsLocation(effect: Effect, uniforms: string[], partId: number) {
  238. // let i = this.getPartIndexFromId(partId);
  239. // if (i === null) {
  240. // return null;
  241. // }
  242. // let pci = this._partsClassInfo[i];
  243. // pci.fullContent.forEach((k, v) => {
  244. // if (uniforms.indexOf(v.attributeName) !== -1) {
  245. // v.uniformLocation = effect.getUniform(v.attributeName);
  246. // }
  247. // });
  248. //}
  249. private static v2 = Vector2.Zero();
  250. private static v3 = Vector3.Zero();
  251. private static v4 = Vector4.Zero();
  252. protected setupUniforms(effect: Effect, partIndex: number, data: DynamicFloatArray, elementCount: number) {
  253. let pd = this._partData[partIndex];
  254. let offset = (pd._partDataStride/4) * elementCount;
  255. let pci = this._partsClassInfo[partIndex];
  256. let self = this;
  257. pci.fullContent.forEach((k, v) => {
  258. if (!v.category || pd._partUsedCategories.indexOf(v.category) !== -1) {
  259. switch (v.dataType) {
  260. case ShaderDataType.float:
  261. {
  262. let attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  263. effect.setFloat(v.attributeName, data.buffer[offset + attribOffset]);
  264. break;
  265. }
  266. case ShaderDataType.Vector2:
  267. {
  268. let attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  269. ModelRenderCache.v2.x = data.buffer[offset + attribOffset + 0];
  270. ModelRenderCache.v2.y = data.buffer[offset + attribOffset + 1];
  271. effect.setVector2(v.attributeName, ModelRenderCache.v2);
  272. break;
  273. }
  274. case ShaderDataType.Color3:
  275. case ShaderDataType.Vector3:
  276. {
  277. let attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  278. ModelRenderCache.v3.x = data.buffer[offset + attribOffset + 0];
  279. ModelRenderCache.v3.y = data.buffer[offset + attribOffset + 1];
  280. ModelRenderCache.v3.z = data.buffer[offset + attribOffset + 2];
  281. effect.setVector3(v.attributeName, ModelRenderCache.v3);
  282. break;
  283. }
  284. case ShaderDataType.Color4:
  285. case ShaderDataType.Vector4:
  286. {
  287. let attribOffset = v.instanceOffset.get(pd._partJoinedUsedCategories);
  288. ModelRenderCache.v4.x = data.buffer[offset + attribOffset + 0];
  289. ModelRenderCache.v4.y = data.buffer[offset + attribOffset + 1];
  290. ModelRenderCache.v4.z = data.buffer[offset + attribOffset + 2];
  291. ModelRenderCache.v4.w = data.buffer[offset + attribOffset + 3];
  292. effect.setVector4(v.attributeName, ModelRenderCache.v4);
  293. break;
  294. }
  295. default:
  296. }
  297. }
  298. });
  299. }
  300. protected _engine: Engine;
  301. private _modelKey: string;
  302. private _nextKey: number;
  303. private _refCounter: number;
  304. _partData: ModelRenderCachePartData[];
  305. _partsClassInfo: ClassTreeInfo<InstanceClassInfo, InstancePropInfo>[];
  306. }
  307. export class ModelRenderCachePartData {
  308. _partId: number;
  309. _zBiasOffset: number;
  310. _partDataStride: number;
  311. _partUsedCategories: string[];
  312. _partJoinedUsedCategories: string;
  313. }
  314. }