createUniformArray.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. import Cartesian2 from "../Core/Cartesian2.js";
  2. import Cartesian3 from "../Core/Cartesian3.js";
  3. import Cartesian4 from "../Core/Cartesian4.js";
  4. import Color from "../Core/Color.js";
  5. import defined from "../Core/defined.js";
  6. import DeveloperError from "../Core/DeveloperError.js";
  7. import Matrix2 from "../Core/Matrix2.js";
  8. import Matrix3 from "../Core/Matrix3.js";
  9. import Matrix4 from "../Core/Matrix4.js";
  10. import RuntimeError from "../Core/RuntimeError.js";
  11. /**
  12. * @private
  13. * @constructor
  14. */
  15. function createUniformArray(gl, activeUniform, uniformName, locations) {
  16. switch (activeUniform.type) {
  17. case gl.FLOAT:
  18. return new UniformArrayFloat(gl, activeUniform, uniformName, locations);
  19. case gl.FLOAT_VEC2:
  20. return new UniformArrayFloatVec2(
  21. gl,
  22. activeUniform,
  23. uniformName,
  24. locations
  25. );
  26. case gl.FLOAT_VEC3:
  27. return new UniformArrayFloatVec3(
  28. gl,
  29. activeUniform,
  30. uniformName,
  31. locations
  32. );
  33. case gl.FLOAT_VEC4:
  34. return new UniformArrayFloatVec4(
  35. gl,
  36. activeUniform,
  37. uniformName,
  38. locations
  39. );
  40. case gl.SAMPLER_2D:
  41. case gl.SAMPLER_CUBE:
  42. return new UniformArraySampler(gl, activeUniform, uniformName, locations);
  43. case gl.INT:
  44. case gl.BOOL:
  45. return new UniformArrayInt(gl, activeUniform, uniformName, locations);
  46. case gl.INT_VEC2:
  47. case gl.BOOL_VEC2:
  48. return new UniformArrayIntVec2(gl, activeUniform, uniformName, locations);
  49. case gl.INT_VEC3:
  50. case gl.BOOL_VEC3:
  51. return new UniformArrayIntVec3(gl, activeUniform, uniformName, locations);
  52. case gl.INT_VEC4:
  53. case gl.BOOL_VEC4:
  54. return new UniformArrayIntVec4(gl, activeUniform, uniformName, locations);
  55. case gl.FLOAT_MAT2:
  56. return new UniformArrayMat2(gl, activeUniform, uniformName, locations);
  57. case gl.FLOAT_MAT3:
  58. return new UniformArrayMat3(gl, activeUniform, uniformName, locations);
  59. case gl.FLOAT_MAT4:
  60. return new UniformArrayMat4(gl, activeUniform, uniformName, locations);
  61. default:
  62. throw new RuntimeError(
  63. "Unrecognized uniform type: " +
  64. activeUniform.type +
  65. ' for uniform "' +
  66. uniformName +
  67. '".'
  68. );
  69. }
  70. }
  71. /**
  72. * @private
  73. * @constructor
  74. */
  75. function UniformArrayFloat(gl, activeUniform, uniformName, locations) {
  76. var length = locations.length;
  77. /**
  78. * @type {String}
  79. * @readonly
  80. */
  81. this.name = uniformName;
  82. this.value = new Array(length);
  83. this._value = new Float32Array(length);
  84. this._gl = gl;
  85. this._location = locations[0];
  86. }
  87. UniformArrayFloat.prototype.set = function () {
  88. var value = this.value;
  89. var length = value.length;
  90. var arraybuffer = this._value;
  91. var changed = false;
  92. for (var i = 0; i < length; ++i) {
  93. var v = value[i];
  94. if (v !== arraybuffer[i]) {
  95. arraybuffer[i] = v;
  96. changed = true;
  97. }
  98. }
  99. if (changed) {
  100. this._gl.uniform1fv(this._location, arraybuffer);
  101. }
  102. };
  103. ///////////////////////////////////////////////////////////////////////////
  104. /**
  105. * @private
  106. * @constructor
  107. */
  108. function UniformArrayFloatVec2(gl, activeUniform, uniformName, locations) {
  109. var length = locations.length;
  110. /**
  111. * @type {String}
  112. * @readonly
  113. */
  114. this.name = uniformName;
  115. this.value = new Array(length);
  116. this._value = new Float32Array(length * 2);
  117. this._gl = gl;
  118. this._location = locations[0];
  119. }
  120. UniformArrayFloatVec2.prototype.set = function () {
  121. var value = this.value;
  122. var length = value.length;
  123. var arraybuffer = this._value;
  124. var changed = false;
  125. var j = 0;
  126. for (var i = 0; i < length; ++i) {
  127. var v = value[i];
  128. if (!Cartesian2.equalsArray(v, arraybuffer, j)) {
  129. Cartesian2.pack(v, arraybuffer, j);
  130. changed = true;
  131. }
  132. j += 2;
  133. }
  134. if (changed) {
  135. this._gl.uniform2fv(this._location, arraybuffer);
  136. }
  137. };
  138. ///////////////////////////////////////////////////////////////////////////
  139. /**
  140. * @private
  141. * @constructor
  142. */
  143. function UniformArrayFloatVec3(gl, activeUniform, uniformName, locations) {
  144. var length = locations.length;
  145. /**
  146. * @type {String}
  147. * @readonly
  148. */
  149. this.name = uniformName;
  150. this.value = new Array(length);
  151. this._value = new Float32Array(length * 3);
  152. this._gl = gl;
  153. this._location = locations[0];
  154. }
  155. UniformArrayFloatVec3.prototype.set = function () {
  156. var value = this.value;
  157. var length = value.length;
  158. var arraybuffer = this._value;
  159. var changed = false;
  160. var j = 0;
  161. for (var i = 0; i < length; ++i) {
  162. var v = value[i];
  163. if (defined(v.red)) {
  164. if (
  165. v.red !== arraybuffer[j] ||
  166. v.green !== arraybuffer[j + 1] ||
  167. v.blue !== arraybuffer[j + 2]
  168. ) {
  169. arraybuffer[j] = v.red;
  170. arraybuffer[j + 1] = v.green;
  171. arraybuffer[j + 2] = v.blue;
  172. changed = true;
  173. }
  174. } else if (defined(v.x)) {
  175. if (!Cartesian3.equalsArray(v, arraybuffer, j)) {
  176. Cartesian3.pack(v, arraybuffer, j);
  177. changed = true;
  178. }
  179. } else {
  180. //>>includeStart('debug', pragmas.debug);
  181. throw new DeveloperError("Invalid vec3 value.");
  182. //>>includeEnd('debug');
  183. }
  184. j += 3;
  185. }
  186. if (changed) {
  187. this._gl.uniform3fv(this._location, arraybuffer);
  188. }
  189. };
  190. ///////////////////////////////////////////////////////////////////////////
  191. /**
  192. * @private
  193. * @constructor
  194. */
  195. function UniformArrayFloatVec4(gl, activeUniform, uniformName, locations) {
  196. var length = locations.length;
  197. /**
  198. * @type {String}
  199. * @readonly
  200. */
  201. this.name = uniformName;
  202. this.value = new Array(length);
  203. this._value = new Float32Array(length * 4);
  204. this._gl = gl;
  205. this._location = locations[0];
  206. }
  207. UniformArrayFloatVec4.prototype.set = function () {
  208. // PERFORMANCE_IDEA: if it is a common case that only a few elements
  209. // in a uniform array change, we could use heuristics to determine
  210. // when it is better to call uniform4f for each element that changed
  211. // vs. call uniform4fv once to set the entire array. This applies
  212. // to all uniform array types, not just vec4. We might not care
  213. // once we have uniform buffers since that will be the fast path.
  214. // PERFORMANCE_IDEA: Micro-optimization (I bet it works though):
  215. // As soon as changed is true, break into a separate loop that
  216. // does the copy without the equals check.
  217. var value = this.value;
  218. var length = value.length;
  219. var arraybuffer = this._value;
  220. var changed = false;
  221. var j = 0;
  222. for (var i = 0; i < length; ++i) {
  223. var v = value[i];
  224. if (defined(v.red)) {
  225. if (!Color.equalsArray(v, arraybuffer, j)) {
  226. Color.pack(v, arraybuffer, j);
  227. changed = true;
  228. }
  229. } else if (defined(v.x)) {
  230. if (!Cartesian4.equalsArray(v, arraybuffer, j)) {
  231. Cartesian4.pack(v, arraybuffer, j);
  232. changed = true;
  233. }
  234. } else {
  235. //>>includeStart('debug', pragmas.debug);
  236. throw new DeveloperError("Invalid vec4 value.");
  237. //>>includeEnd('debug');
  238. }
  239. j += 4;
  240. }
  241. if (changed) {
  242. this._gl.uniform4fv(this._location, arraybuffer);
  243. }
  244. };
  245. ///////////////////////////////////////////////////////////////////////////
  246. /**
  247. * @private
  248. * @constructor
  249. */
  250. function UniformArraySampler(gl, activeUniform, uniformName, locations) {
  251. var length = locations.length;
  252. /**
  253. * @type {String}
  254. * @readonly
  255. */
  256. this.name = uniformName;
  257. this.value = new Array(length);
  258. this._value = new Float32Array(length);
  259. this._gl = gl;
  260. this._locations = locations;
  261. this.textureUnitIndex = undefined;
  262. }
  263. UniformArraySampler.prototype.set = function () {
  264. var gl = this._gl;
  265. var textureUnitIndex = gl.TEXTURE0 + this.textureUnitIndex;
  266. var value = this.value;
  267. var length = value.length;
  268. for (var i = 0; i < length; ++i) {
  269. var v = value[i];
  270. gl.activeTexture(textureUnitIndex + i);
  271. gl.bindTexture(v._target, v._texture);
  272. }
  273. };
  274. UniformArraySampler.prototype._setSampler = function (textureUnitIndex) {
  275. this.textureUnitIndex = textureUnitIndex;
  276. var locations = this._locations;
  277. var length = locations.length;
  278. for (var i = 0; i < length; ++i) {
  279. var index = textureUnitIndex + i;
  280. this._gl.uniform1i(locations[i], index);
  281. }
  282. return textureUnitIndex + length;
  283. };
  284. ///////////////////////////////////////////////////////////////////////////
  285. /**
  286. * @private
  287. * @constructor
  288. */
  289. function UniformArrayInt(gl, activeUniform, uniformName, locations) {
  290. var length = locations.length;
  291. /**
  292. * @type {String}
  293. * @readonly
  294. */
  295. this.name = uniformName;
  296. this.value = new Array(length);
  297. this._value = new Int32Array(length);
  298. this._gl = gl;
  299. this._location = locations[0];
  300. }
  301. UniformArrayInt.prototype.set = function () {
  302. var value = this.value;
  303. var length = value.length;
  304. var arraybuffer = this._value;
  305. var changed = false;
  306. for (var i = 0; i < length; ++i) {
  307. var v = value[i];
  308. if (v !== arraybuffer[i]) {
  309. arraybuffer[i] = v;
  310. changed = true;
  311. }
  312. }
  313. if (changed) {
  314. this._gl.uniform1iv(this._location, arraybuffer);
  315. }
  316. };
  317. ///////////////////////////////////////////////////////////////////////////
  318. /**
  319. * @private
  320. * @constructor
  321. */
  322. function UniformArrayIntVec2(gl, activeUniform, uniformName, locations) {
  323. var length = locations.length;
  324. /**
  325. * @type {String}
  326. * @readonly
  327. */
  328. this.name = uniformName;
  329. this.value = new Array(length);
  330. this._value = new Int32Array(length * 2);
  331. this._gl = gl;
  332. this._location = locations[0];
  333. }
  334. UniformArrayIntVec2.prototype.set = function () {
  335. var value = this.value;
  336. var length = value.length;
  337. var arraybuffer = this._value;
  338. var changed = false;
  339. var j = 0;
  340. for (var i = 0; i < length; ++i) {
  341. var v = value[i];
  342. if (!Cartesian2.equalsArray(v, arraybuffer, j)) {
  343. Cartesian2.pack(v, arraybuffer, j);
  344. changed = true;
  345. }
  346. j += 2;
  347. }
  348. if (changed) {
  349. this._gl.uniform2iv(this._location, arraybuffer);
  350. }
  351. };
  352. ///////////////////////////////////////////////////////////////////////////
  353. /**
  354. * @private
  355. * @constructor
  356. */
  357. function UniformArrayIntVec3(gl, activeUniform, uniformName, locations) {
  358. var length = locations.length;
  359. /**
  360. * @type {String}
  361. * @readonly
  362. */
  363. this.name = uniformName;
  364. this.value = new Array(length);
  365. this._value = new Int32Array(length * 3);
  366. this._gl = gl;
  367. this._location = locations[0];
  368. }
  369. UniformArrayIntVec3.prototype.set = function () {
  370. var value = this.value;
  371. var length = value.length;
  372. var arraybuffer = this._value;
  373. var changed = false;
  374. var j = 0;
  375. for (var i = 0; i < length; ++i) {
  376. var v = value[i];
  377. if (!Cartesian3.equalsArray(v, arraybuffer, j)) {
  378. Cartesian3.pack(v, arraybuffer, j);
  379. changed = true;
  380. }
  381. j += 3;
  382. }
  383. if (changed) {
  384. this._gl.uniform3iv(this._location, arraybuffer);
  385. }
  386. };
  387. ///////////////////////////////////////////////////////////////////////////
  388. /**
  389. * @private
  390. * @constructor
  391. */
  392. function UniformArrayIntVec4(gl, activeUniform, uniformName, locations) {
  393. var length = locations.length;
  394. /**
  395. * @type {String}
  396. * @readonly
  397. */
  398. this.name = uniformName;
  399. this.value = new Array(length);
  400. this._value = new Int32Array(length * 4);
  401. this._gl = gl;
  402. this._location = locations[0];
  403. }
  404. UniformArrayIntVec4.prototype.set = function () {
  405. var value = this.value;
  406. var length = value.length;
  407. var arraybuffer = this._value;
  408. var changed = false;
  409. var j = 0;
  410. for (var i = 0; i < length; ++i) {
  411. var v = value[i];
  412. if (!Cartesian4.equalsArray(v, arraybuffer, j)) {
  413. Cartesian4.pack(v, arraybuffer, j);
  414. changed = true;
  415. }
  416. j += 4;
  417. }
  418. if (changed) {
  419. this._gl.uniform4iv(this._location, arraybuffer);
  420. }
  421. };
  422. ///////////////////////////////////////////////////////////////////////////
  423. /**
  424. * @private
  425. * @constructor
  426. */
  427. function UniformArrayMat2(gl, activeUniform, uniformName, locations) {
  428. var length = locations.length;
  429. /**
  430. * @type {String}
  431. * @readonly
  432. */
  433. this.name = uniformName;
  434. this.value = new Array(length);
  435. this._value = new Float32Array(length * 4);
  436. this._gl = gl;
  437. this._location = locations[0];
  438. }
  439. UniformArrayMat2.prototype.set = function () {
  440. var value = this.value;
  441. var length = value.length;
  442. var arraybuffer = this._value;
  443. var changed = false;
  444. var j = 0;
  445. for (var i = 0; i < length; ++i) {
  446. var v = value[i];
  447. if (!Matrix2.equalsArray(v, arraybuffer, j)) {
  448. Matrix2.pack(v, arraybuffer, j);
  449. changed = true;
  450. }
  451. j += 4;
  452. }
  453. if (changed) {
  454. this._gl.uniformMatrix2fv(this._location, false, arraybuffer);
  455. }
  456. };
  457. ///////////////////////////////////////////////////////////////////////////
  458. /**
  459. * @private
  460. * @constructor
  461. */
  462. function UniformArrayMat3(gl, activeUniform, uniformName, locations) {
  463. var length = locations.length;
  464. /**
  465. * @type {String}
  466. * @readonly
  467. */
  468. this.name = uniformName;
  469. this.value = new Array(length);
  470. this._value = new Float32Array(length * 9);
  471. this._gl = gl;
  472. this._location = locations[0];
  473. }
  474. UniformArrayMat3.prototype.set = function () {
  475. var value = this.value;
  476. var length = value.length;
  477. var arraybuffer = this._value;
  478. var changed = false;
  479. var j = 0;
  480. for (var i = 0; i < length; ++i) {
  481. var v = value[i];
  482. if (!Matrix3.equalsArray(v, arraybuffer, j)) {
  483. Matrix3.pack(v, arraybuffer, j);
  484. changed = true;
  485. }
  486. j += 9;
  487. }
  488. if (changed) {
  489. this._gl.uniformMatrix3fv(this._location, false, arraybuffer);
  490. }
  491. };
  492. ///////////////////////////////////////////////////////////////////////////
  493. /**
  494. * @private
  495. * @constructor
  496. */
  497. function UniformArrayMat4(gl, activeUniform, uniformName, locations) {
  498. var length = locations.length;
  499. /**
  500. * @type {String}
  501. * @readonly
  502. */
  503. this.name = uniformName;
  504. this.value = new Array(length);
  505. this._value = new Float32Array(length * 16);
  506. this._gl = gl;
  507. this._location = locations[0];
  508. }
  509. UniformArrayMat4.prototype.set = function () {
  510. var value = this.value;
  511. var length = value.length;
  512. var arraybuffer = this._value;
  513. var changed = false;
  514. var j = 0;
  515. for (var i = 0; i < length; ++i) {
  516. var v = value[i];
  517. if (!Matrix4.equalsArray(v, arraybuffer, j)) {
  518. Matrix4.pack(v, arraybuffer, j);
  519. changed = true;
  520. }
  521. j += 16;
  522. }
  523. if (changed) {
  524. this._gl.uniformMatrix4fv(this._location, false, arraybuffer);
  525. }
  526. };
  527. export default createUniformArray;