CCDrawingPrimitivesWebGL.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2011-2012 cocos2d-x.org
  4. Copyright (c) 2013-2014 Chukong Technologies Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. /**
  23. * Canvas of DrawingPrimitive implement version use for WebGlMode
  24. * @class
  25. * @extends cc.Class
  26. */
  27. cc.DrawingPrimitiveWebGL = cc.Class.extend(/** @lends cc.DrawingPrimitiveWebGL# */{
  28. _renderContext:null,
  29. _initialized:false,
  30. _shader: null,
  31. _colorLocation:-1,
  32. _colorArray: null,
  33. _pointSizeLocation:-1,
  34. _pointSize:-1,
  35. /**
  36. * contructor of cc.DrawingPrimitiveWebGL
  37. * @param ctx rendercontext
  38. */
  39. ctor:function (ctx) {
  40. if (ctx == null)
  41. ctx = cc._renderContext;
  42. if (!ctx instanceof WebGLRenderingContext)
  43. throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext";
  44. this._renderContext = ctx;
  45. this._colorArray = new Float32Array([1.0, 1.0, 1.0, 1.0]);
  46. },
  47. lazy_init:function () {
  48. var _t = this;
  49. if (!_t._initialized) {
  50. //
  51. // Position and 1 color passed as a uniform (to similate glColor4ub )
  52. //
  53. _t._shader = cc.shaderCache.programForKey(cc.SHADER_POSITION_UCOLOR);
  54. _t._colorLocation = _t._renderContext.getUniformLocation(_t._shader.getProgram(), "u_color");
  55. _t._pointSizeLocation = _t._renderContext.getUniformLocation(_t._shader.getProgram(), "u_pointSize");
  56. _t._initialized = true;
  57. }
  58. },
  59. /**
  60. * initlialize context
  61. */
  62. drawInit:function () {
  63. this._initialized = false;
  64. },
  65. /**
  66. * draws a point given x and y coordinate measured in points
  67. * @param {cc.Point} point
  68. */
  69. drawPoint:function (point) {
  70. this.lazy_init();
  71. var glContext = this._renderContext;
  72. this._shader.use();
  73. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  74. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  75. glContext.uniform4fv(this._colorLocation, this._colorArray);
  76. this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
  77. var pointBuffer = glContext.createBuffer();
  78. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  79. glContext.bufferData(glContext.ARRAY_BUFFER, new Float32Array([point.x, point.y]), glContext.STATIC_DRAW);
  80. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  81. glContext.drawArrays(glContext.POINTS, 0, 1);
  82. glContext.deleteBuffer(pointBuffer);
  83. cc.incrementGLDraws(1);
  84. },
  85. /**
  86. * draws an array of points.
  87. * @param {Array} points point of array
  88. * @param {Number} numberOfPoints
  89. */
  90. drawPoints:function (points, numberOfPoints) {
  91. if (!points || points.length == 0)
  92. return;
  93. this.lazy_init();
  94. var glContext = this._renderContext;
  95. this._shader.use();
  96. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  97. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  98. glContext.uniform4fv(this._colorLocation, this._colorArray);
  99. this._shader.setUniformLocationWith1f(this._pointSizeLocation, this._pointSize);
  100. var pointBuffer = glContext.createBuffer();
  101. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  102. glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(points), glContext.STATIC_DRAW);
  103. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  104. glContext.drawArrays(glContext.POINTS, 0, points.length);
  105. glContext.deleteBuffer(pointBuffer);
  106. cc.incrementGLDraws(1);
  107. },
  108. _pointsToTypeArray:function (points) {
  109. var typeArr = new Float32Array(points.length * 2);
  110. for (var i = 0; i < points.length; i++) {
  111. typeArr[i * 2] = points[i].x;
  112. typeArr[i * 2 + 1] = points[i].y;
  113. }
  114. return typeArr;
  115. },
  116. /**
  117. * draws a line given the origin and destination point measured in points
  118. * @param {cc.Point} origin
  119. * @param {cc.Point} destination
  120. */
  121. drawLine:function (origin, destination) {
  122. this.lazy_init();
  123. var glContext = this._renderContext;
  124. this._shader.use();
  125. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  126. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  127. glContext.uniform4fv(this._colorLocation, this._colorArray);
  128. var pointBuffer = glContext.createBuffer();
  129. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  130. glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray([origin, destination]), glContext.STATIC_DRAW);
  131. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  132. glContext.drawArrays(glContext.LINES, 0, 2);
  133. glContext.deleteBuffer(pointBuffer);
  134. cc.incrementGLDraws(1);
  135. },
  136. /**
  137. * draws a rectangle given the origin and destination point measured in points.
  138. * @param {cc.Point} origin
  139. * @param {cc.Point} destination
  140. */
  141. drawRect:function (origin, destination) {
  142. this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
  143. this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
  144. this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
  145. this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
  146. },
  147. /**
  148. * draws a solid rectangle given the origin and destination point measured in points.
  149. * @param {cc.Point} origin
  150. * @param {cc.Point} destination
  151. * @param {cc.Color} color
  152. */
  153. drawSolidRect:function (origin, destination, color) {
  154. var vertices = [
  155. origin,
  156. cc.p(destination.x, origin.y),
  157. destination,
  158. cc.p(origin.x, destination.y)
  159. ];
  160. this.drawSolidPoly(vertices, 4, color);
  161. },
  162. /**
  163. * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points.
  164. * @param {Array} vertices a pointer to cc.Point coordiantes
  165. * @param {Number} numOfVertices the number of vertices measured in points
  166. * @param {Boolean} closePolygon The polygon can be closed or open
  167. */
  168. drawPoly:function (vertices, numOfVertices, closePolygon) {
  169. this.lazy_init();
  170. var glContext = this._renderContext;
  171. this._shader.use();
  172. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  173. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  174. glContext.uniform4fv(this._colorLocation, this._colorArray);
  175. var pointBuffer = glContext.createBuffer();
  176. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  177. glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(vertices), glContext.STATIC_DRAW);
  178. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  179. if (closePolygon)
  180. glContext.drawArrays(glContext.LINE_LOOP, 0, vertices.length);
  181. else
  182. glContext.drawArrays(glContext.LINE_STRIP, 0, vertices.length);
  183. glContext.deleteBuffer(pointBuffer);
  184. cc.incrementGLDraws(1);
  185. },
  186. /**
  187. * draws a solid polygon given a pointer to CGPoint coordiantes, the number of vertices measured in points, and a color.
  188. * @param {Array} poli
  189. * @param {Number} numberOfPoints
  190. * @param {cc.Color} color
  191. */
  192. drawSolidPoly:function (poli, numberOfPoints, color) {
  193. this.lazy_init();
  194. if (color)
  195. this.setDrawColor(color.r, color.g, color.b, color.a);
  196. var glContext = this._renderContext;
  197. this._shader.use();
  198. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  199. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  200. glContext.uniform4fv(this._colorLocation, this._colorArray);
  201. var pointBuffer = glContext.createBuffer();
  202. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  203. glContext.bufferData(glContext.ARRAY_BUFFER, this._pointsToTypeArray(poli), glContext.STATIC_DRAW);
  204. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  205. glContext.drawArrays(glContext.TRIANGLE_FAN, 0, poli.length);
  206. glContext.deleteBuffer(pointBuffer);
  207. cc.incrementGLDraws(1);
  208. },
  209. /**
  210. * draws a circle given the center, radius and number of segments.
  211. * @param {cc.Point} center center of circle
  212. * @param {Number} radius
  213. * @param {Number} angle angle in radians
  214. * @param {Number} segments
  215. * @param {Boolean} drawLineToCenter
  216. */
  217. drawCircle:function (center, radius, angle, segments, drawLineToCenter) {
  218. this.lazy_init();
  219. var additionalSegment = 1;
  220. if (drawLineToCenter)
  221. additionalSegment++;
  222. var coef = 2.0 * Math.PI / segments;
  223. var vertices = new Float32Array((segments + 2) * 2);
  224. if (!vertices)
  225. return;
  226. for (var i = 0; i <= segments; i++) {
  227. var rads = i * coef;
  228. var j = radius * Math.cos(rads + angle) + center.x;
  229. var k = radius * Math.sin(rads + angle) + center.y;
  230. vertices[i * 2] = j;
  231. vertices[i * 2 + 1] = k;
  232. }
  233. vertices[(segments + 1) * 2] = center.x;
  234. vertices[(segments + 1) * 2 + 1] = center.y;
  235. var glContext = this._renderContext;
  236. this._shader.use();
  237. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  238. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  239. glContext.uniform4fv(this._colorLocation, this._colorArray);
  240. var pointBuffer = glContext.createBuffer();
  241. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  242. glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
  243. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  244. glContext.drawArrays(glContext.LINE_STRIP, 0, segments + additionalSegment);
  245. glContext.deleteBuffer(pointBuffer);
  246. cc.incrementGLDraws(1);
  247. },
  248. /**
  249. * draws a quad bezier path
  250. * @param {cc.Point} origin
  251. * @param {cc.Point} control
  252. * @param {cc.Point} destination
  253. * @param {Number} segments
  254. */
  255. drawQuadBezier:function (origin, control, destination, segments) {
  256. this.lazy_init();
  257. var vertices = new Float32Array((segments + 1) * 2);
  258. var t = 0.0;
  259. for (var i = 0; i < segments; i++) {
  260. vertices[i * 2] = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
  261. vertices[i * 2 + 1] = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
  262. t += 1.0 / segments;
  263. }
  264. vertices[segments * 2] = destination.x;
  265. vertices[segments * 2 + 1] = destination.y;
  266. var glContext = this._renderContext;
  267. this._shader.use();
  268. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  269. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  270. glContext.uniform4fv(this._colorLocation, this._colorArray);
  271. var pointBuffer = glContext.createBuffer();
  272. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  273. glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
  274. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  275. glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
  276. glContext.deleteBuffer(pointBuffer);
  277. cc.incrementGLDraws(1);
  278. },
  279. /**
  280. * draws a cubic bezier path
  281. * @param {cc.Point} origin
  282. * @param {cc.Point} control1
  283. * @param {cc.Point} control2
  284. * @param {cc.Point} destination
  285. * @param {Number} segments
  286. */
  287. drawCubicBezier:function (origin, control1, control2, destination, segments) {
  288. this.lazy_init();
  289. var vertices = new Float32Array((segments + 1) * 2);
  290. var t = 0;
  291. for (var i = 0; i < segments; i++) {
  292. vertices[i * 2] = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
  293. vertices[i * 2 + 1] = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
  294. t += 1.0 / segments;
  295. }
  296. vertices[segments * 2] = destination.x;
  297. vertices[segments * 2 + 1] = destination.y;
  298. var glContext = this._renderContext;
  299. this._shader.use();
  300. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  301. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  302. glContext.uniform4fv(this._colorLocation, this._colorArray);
  303. var pointBuffer = glContext.createBuffer();
  304. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  305. glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
  306. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  307. glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
  308. glContext.deleteBuffer(pointBuffer);
  309. cc.incrementGLDraws(1);
  310. },
  311. /**
  312. * draw a catmull rom line
  313. * @param {Array} points
  314. * @param {Number} segments
  315. */
  316. drawCatmullRom:function (points, segments) {
  317. this.drawCardinalSpline(points, 0.5, segments);
  318. },
  319. /**
  320. * draw a cardinal spline path
  321. * @param {Array} config
  322. * @param {Number} tension
  323. * @param {Number} segments
  324. */
  325. drawCardinalSpline:function (config, tension, segments) {
  326. this.lazy_init();
  327. var vertices = new Float32Array((segments + 1) * 2);
  328. var p, lt, deltaT = 1.0 / config.length;
  329. for (var i = 0; i < segments + 1; i++) {
  330. var dt = i / segments;
  331. // border
  332. if (dt == 1) {
  333. p = config.length - 1;
  334. lt = 1;
  335. } else {
  336. p = 0 | (dt / deltaT);
  337. lt = (dt - deltaT * p) / deltaT;
  338. }
  339. var newPos = cc.CardinalSplineAt(
  340. cc.getControlPointAt(config, p - 1),
  341. cc.getControlPointAt(config, p),
  342. cc.getControlPointAt(config, p + 1),
  343. cc.getControlPointAt(config, p + 2),
  344. tension, lt);
  345. // Interpolate
  346. vertices[i * 2] = newPos.x;
  347. vertices[i * 2 + 1] = newPos.y;
  348. }
  349. var glContext = this._renderContext;
  350. this._shader.use();
  351. this._shader.setUniformForModelViewAndProjectionMatrixWithMat4();
  352. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION);
  353. glContext.uniform4fv(this._colorLocation, this._colorArray);
  354. var pointBuffer = glContext.createBuffer();
  355. glContext.bindBuffer(glContext.ARRAY_BUFFER, pointBuffer);
  356. glContext.bufferData(glContext.ARRAY_BUFFER, vertices, glContext.STATIC_DRAW);
  357. glContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, glContext.FLOAT, false, 0, 0);
  358. glContext.drawArrays(glContext.LINE_STRIP, 0, segments + 1);
  359. glContext.deleteBuffer(pointBuffer);
  360. cc.incrementGLDraws(1);
  361. },
  362. /**
  363. * set the drawing color with 4 unsigned bytes
  364. * @param {Number} r red value (0 to 255)
  365. * @param {Number} g green value (0 to 255)
  366. * @param {Number} b blue value (0 to 255)
  367. * @param {Number} a Alpha value (0 to 255)
  368. */
  369. setDrawColor:function (r, g, b, a) {
  370. this._colorArray[0] = r / 255.0;
  371. this._colorArray[1] = g / 255.0;
  372. this._colorArray[2] = b / 255.0;
  373. this._colorArray[3] = a / 255.0;
  374. },
  375. /**
  376. * set the point size in points. Default 1.
  377. * @param {Number} pointSize
  378. */
  379. setPointSize:function (pointSize) {
  380. this._pointSize = pointSize * cc.contentScaleFactor();
  381. },
  382. /**
  383. * set the line width. Default 1.
  384. * @param {Number} width
  385. */
  386. setLineWidth:function (width) {
  387. if(this._renderContext.lineWidth)
  388. this._renderContext.lineWidth(width);
  389. }
  390. });