Context.js 98 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361
  1. /*global define*/
  2. define([
  3. '../Core/clone',
  4. '../Core/Color',
  5. '../Core/ComponentDatatype',
  6. '../Core/createGuid',
  7. '../Core/defaultValue',
  8. '../Core/defined',
  9. '../Core/defineProperties',
  10. '../Core/destroyObject',
  11. '../Core/DeveloperError',
  12. '../Core/Geometry',
  13. '../Core/GeometryAttribute',
  14. '../Core/IndexDatatype',
  15. '../Core/Math',
  16. '../Core/Matrix4',
  17. '../Core/PixelFormat',
  18. '../Core/PrimitiveType',
  19. '../Core/RuntimeError',
  20. '../Shaders/ViewportQuadVS',
  21. './Buffer',
  22. './BufferUsage',
  23. './ClearCommand',
  24. './CubeMap',
  25. './DrawCommand',
  26. './Framebuffer',
  27. './PassState',
  28. './PickFramebuffer',
  29. './PixelDatatype',
  30. './Renderbuffer',
  31. './RenderbufferFormat',
  32. './RenderState',
  33. './ShaderCache',
  34. './Texture',
  35. './TextureMagnificationFilter',
  36. './TextureMinificationFilter',
  37. './TextureWrap',
  38. './UniformState',
  39. './VertexArray'
  40. ], function(
  41. clone,
  42. Color,
  43. ComponentDatatype,
  44. createGuid,
  45. defaultValue,
  46. defined,
  47. defineProperties,
  48. destroyObject,
  49. DeveloperError,
  50. Geometry,
  51. GeometryAttribute,
  52. IndexDatatype,
  53. CesiumMath,
  54. Matrix4,
  55. PixelFormat,
  56. PrimitiveType,
  57. RuntimeError,
  58. ViewportQuadVS,
  59. Buffer,
  60. BufferUsage,
  61. ClearCommand,
  62. CubeMap,
  63. DrawCommand,
  64. Framebuffer,
  65. PassState,
  66. PickFramebuffer,
  67. PixelDatatype,
  68. Renderbuffer,
  69. RenderbufferFormat,
  70. RenderState,
  71. ShaderCache,
  72. Texture,
  73. TextureMagnificationFilter,
  74. TextureMinificationFilter,
  75. TextureWrap,
  76. UniformState,
  77. VertexArray) {
  78. "use strict";
  79. /*global WebGLRenderingContext*/
  80. function errorToString(gl, error) {
  81. var message = 'WebGL Error: ';
  82. switch (error) {
  83. case gl.INVALID_ENUM:
  84. message += 'INVALID_ENUM';
  85. break;
  86. case gl.INVALID_VALUE:
  87. message += 'INVALID_VALUE';
  88. break;
  89. case gl.INVALID_OPERATION:
  90. message += 'INVALID_OPERATION';
  91. break;
  92. case gl.OUT_OF_MEMORY:
  93. message += 'OUT_OF_MEMORY';
  94. break;
  95. case gl.CONTEXT_LOST_WEBGL:
  96. message += 'CONTEXT_LOST_WEBGL lost';
  97. break;
  98. default:
  99. message += 'Unknown (' + error + ')';
  100. }
  101. return message;
  102. }
  103. function createErrorMessage(gl, glFunc, glFuncArguments, error) {
  104. var message = errorToString(gl, error) + ': ' + glFunc.name + '(';
  105. for ( var i = 0; i < glFuncArguments.length; ++i) {
  106. if (i !== 0) {
  107. message += ', ';
  108. }
  109. message += glFuncArguments[i];
  110. }
  111. message += ');';
  112. return message;
  113. }
  114. function throwOnError(gl, glFunc, glFuncArguments) {
  115. var error = gl.getError();
  116. if (error !== gl.NO_ERROR) {
  117. throw new RuntimeError(createErrorMessage(gl, glFunc, glFuncArguments, error));
  118. }
  119. }
  120. function makeGetterSetter(gl, propertyName, logFunc) {
  121. return {
  122. get : function() {
  123. var value = gl[propertyName];
  124. logFunc(gl, 'get: ' + propertyName, value);
  125. return gl[propertyName];
  126. },
  127. set : function(value) {
  128. gl[propertyName] = value;
  129. logFunc(gl, 'set: ' + propertyName, value);
  130. }
  131. };
  132. }
  133. function wrapGL(gl, logFunc) {
  134. if (!logFunc) {
  135. return gl;
  136. }
  137. function wrapFunction(property) {
  138. return function() {
  139. var result = property.apply(gl, arguments);
  140. logFunc(gl, property, arguments);
  141. return result;
  142. };
  143. }
  144. var glWrapper = {};
  145. /*jslint forin: true*/
  146. /*jshint forin: false*/
  147. // JSLint normally demands that a for..in loop must directly contain an if,
  148. // but in our loop below, we actually intend to iterate all properties, including
  149. // those in the prototype.
  150. for ( var propertyName in gl) {
  151. var property = gl[propertyName];
  152. // wrap any functions we encounter, otherwise just copy the property to the wrapper.
  153. if (typeof property === 'function') {
  154. glWrapper[propertyName] = wrapFunction(property);
  155. } else {
  156. Object.defineProperty(glWrapper, propertyName, makeGetterSetter(gl, propertyName, logFunc));
  157. }
  158. }
  159. return glWrapper;
  160. }
  161. function getExtension(gl, names) {
  162. var length = names.length;
  163. for (var i = 0; i < length; ++i) {
  164. var extension = gl.getExtension(names[i]);
  165. if (extension) {
  166. return extension;
  167. }
  168. }
  169. return undefined;
  170. }
  171. /**
  172. * @private
  173. */
  174. var Context = function(canvas, options) {
  175. // this check must use typeof, not defined, because defined doesn't work with undeclared variables.
  176. if (typeof WebGLRenderingContext === 'undefined') {
  177. throw new RuntimeError('The browser does not support WebGL. Visit http://get.webgl.org.');
  178. }
  179. //>>includeStart('debug', pragmas.debug);
  180. if (!defined(canvas)) {
  181. throw new DeveloperError('canvas is required.');
  182. }
  183. //>>includeEnd('debug');
  184. this._canvas = canvas;
  185. options = clone(options, true);
  186. options = defaultValue(options, {});
  187. options.allowTextureFilterAnisotropic = defaultValue(options.allowTextureFilterAnisotropic, true);
  188. var webglOptions = defaultValue(options.webgl, {});
  189. // Override select WebGL defaults
  190. webglOptions.alpha = defaultValue(webglOptions.alpha, false); // WebGL default is true
  191. // TODO: WebGL default is false. This works around a bug in Canary and can be removed when fixed: https://code.google.com/p/chromium/issues/detail?id=335273
  192. webglOptions.stencil = defaultValue(webglOptions.stencil, false);
  193. webglOptions.failIfMajorPerformanceCaveat = defaultValue(webglOptions.failIfMajorPerformanceCaveat, true); // WebGL default is false
  194. this._originalGLContext = canvas.getContext('webgl', webglOptions) || canvas.getContext('experimental-webgl', webglOptions) || undefined;
  195. if (!defined(this._originalGLContext)) {
  196. throw new RuntimeError('The browser supports WebGL, but initialization failed.');
  197. }
  198. this._id = createGuid();
  199. // Validation and logging disabled by default for speed.
  200. this.validateFramebuffer = false;
  201. this.validateShaderProgram = false;
  202. this.logShaderCompilation = false;
  203. this._throwOnWebGLError = false;
  204. this._shaderCache = new ShaderCache(this);
  205. var gl = this._gl = this._originalGLContext;
  206. this._version = gl.getParameter(gl.VERSION);
  207. this._shadingLanguageVersion = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
  208. this._vendor = gl.getParameter(gl.VENDOR);
  209. this._renderer = gl.getParameter(gl.RENDERER);
  210. this._redBits = gl.getParameter(gl.RED_BITS);
  211. this._greenBits = gl.getParameter(gl.GREEN_BITS);
  212. this._blueBits = gl.getParameter(gl.BLUE_BITS);
  213. this._alphaBits = gl.getParameter(gl.ALPHA_BITS);
  214. this._depthBits = gl.getParameter(gl.DEPTH_BITS);
  215. this._stencilBits = gl.getParameter(gl.STENCIL_BITS);
  216. this._maximumCombinedTextureImageUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); // min: 8
  217. this._maximumCubeMapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE); // min: 16
  218. this._maximumFragmentUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS); // min: 16
  219. this._maximumTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); // min: 8
  220. this._maximumRenderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE); // min: 1
  221. this._maximumTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); // min: 64
  222. this._maximumVaryingVectors = gl.getParameter(gl.MAX_VARYING_VECTORS); // min: 8
  223. this._maximumVertexAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); // min: 8
  224. this._maximumVertexTextureImageUnits = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS); // min: 0
  225. this._maximumVertexUniformVectors = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS); // min: 128
  226. this._aliasedLineWidthRange = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE); // must include 1
  227. this._aliasedPointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE); // must include 1
  228. this._maximumViewportDimensions = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
  229. this._antialias = gl.getContextAttributes().antialias;
  230. // Query and initialize extensions
  231. this._standardDerivatives = getExtension(gl, ['OES_standard_derivatives']);
  232. this._elementIndexUint = getExtension(gl, ['OES_element_index_uint']);
  233. this._depthTexture = getExtension(gl, ['WEBGL_depth_texture', 'WEBKIT_WEBGL_depth_texture']);
  234. this._textureFloat = getExtension(gl, ['OES_texture_float']);
  235. var textureFilterAnisotropic = options.allowTextureFilterAnisotropic ? getExtension(gl, ['EXT_texture_filter_anisotropic', 'WEBKIT_EXT_texture_filter_anisotropic']) : undefined;
  236. this._textureFilterAnisotropic = textureFilterAnisotropic;
  237. this._maximumTextureFilterAnisotropy = defined(textureFilterAnisotropic) ? gl.getParameter(textureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1.0;
  238. this._vertexArrayObject = getExtension(gl, ['OES_vertex_array_object']);
  239. this._fragDepth = getExtension(gl, ['EXT_frag_depth']);
  240. this._drawBuffers = getExtension(gl, ['WEBGL_draw_buffers']);
  241. this._maximumDrawBuffers = defined(this._drawBuffers) ? gl.getParameter(this._drawBuffers.MAX_DRAW_BUFFERS_WEBGL) : 1;
  242. this._maximumColorAttachments = defined(this._drawBuffers) ? gl.getParameter(this._drawBuffers.MAX_COLOR_ATTACHMENTS_WEBGL) : 1; // min when supported: 4
  243. this._debugShaders = getExtension(gl, ['WEBGL_debug_shaders']);
  244. var cc = gl.getParameter(gl.COLOR_CLEAR_VALUE);
  245. this._clearColor = new Color(cc[0], cc[1], cc[2], cc[3]);
  246. this._clearDepth = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
  247. this._clearStencil = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
  248. var us = new UniformState();
  249. var ps = new PassState(this);
  250. var rs = this.createRenderState();
  251. this._defaultPassState = ps;
  252. this._defaultRenderState = rs;
  253. this._defaultTexture = undefined;
  254. this._defaultCubeMap = undefined;
  255. this._us = us;
  256. this._currentRenderState = rs;
  257. this._currentFramebuffer = undefined;
  258. this._maxFrameTextureUnitIndex = 0;
  259. this._pickObjects = {};
  260. this._nextPickColor = new Uint32Array(1);
  261. /**
  262. * @example
  263. * {
  264. * webgl : {
  265. * alpha : false,
  266. * depth : true,
  267. * stencil : false,
  268. * antialias : true,
  269. * premultipliedAlpha : true,
  270. * preserveDrawingBuffer : false
  271. * failIfMajorPerformanceCaveat : true
  272. * },
  273. * allowTextureFilterAnisotropic : true
  274. * }
  275. */
  276. this.options = options;
  277. /**
  278. * A cache of objects tied to this context. Just before the Context is destroyed,
  279. * <code>destroy</code> will be invoked on each object in this object literal that has
  280. * such a method. This is useful for caching any objects that might otherwise
  281. * be stored globally, except they're tied to a particular context, and to manage
  282. * their lifetime.
  283. *
  284. * @type {Object}
  285. */
  286. this.cache = {};
  287. RenderState.apply(gl, rs, ps);
  288. };
  289. var defaultFramebufferMarker = {};
  290. defineProperties(Context.prototype, {
  291. id : {
  292. get : function() {
  293. return this._id;
  294. }
  295. },
  296. canvas : {
  297. get : function() {
  298. return this._canvas;
  299. }
  300. },
  301. shaderCache : {
  302. get : function() {
  303. return this._shaderCache;
  304. }
  305. },
  306. uniformState : {
  307. get : function() {
  308. return this._us;
  309. }
  310. },
  311. /**
  312. * The WebGL version or release number of the form &lt;WebGL&gt;&lt;space&gt;&lt;version number&gt;&lt;space&gt;&lt;vendor-specific information&gt;.
  313. * @memberof Context.prototype
  314. * @type {String}
  315. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetString.xml|glGetString} with <code>VERSION</code>.
  316. */
  317. version : {
  318. get : function() {
  319. return this._version;
  320. }
  321. },
  322. /**
  323. * The version or release number for the shading language of the form WebGL&lt;space&gt;GLSL&lt;space&gt;ES&lt;space&gt;&lt;version number&gt;&lt;space&gt;&lt;vendor-specific information&gt;.
  324. * @memberof Context.prototype
  325. * @type {String}
  326. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetString.xml|glGetString} with <code>SHADING_LANGUAGE_VERSION</code>.
  327. */
  328. shadingLanguageVersion : {
  329. get : function() {
  330. return this._shadingLanguageVersion;
  331. }
  332. },
  333. /**
  334. * The company responsible for the WebGL implementation.
  335. * @memberof Context.prototype
  336. * @type {String}
  337. */
  338. vendor : {
  339. get : function() {
  340. return this._vendor;
  341. }
  342. },
  343. /**
  344. * The name of the renderer/configuration/hardware platform. For example, this may be the model of the
  345. * video card, e.g., 'GeForce 8800 GTS/PCI/SSE2', or the browser-dependent name of the GL implementation, e.g.
  346. * 'Mozilla' or 'ANGLE.'
  347. * @memberof Context.prototype
  348. * @type {String}
  349. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetString.xml|glGetString} with <code>RENDERER</code>.
  350. * @see {@link http://code.google.com/p/angleproject/|ANGLE}
  351. */
  352. renderer : {
  353. get : function() {
  354. return this._renderer;
  355. }
  356. },
  357. /**
  358. * The number of red bits per component in the default framebuffer's color buffer. The minimum is eight.
  359. * @memberof Context.prototype
  360. * @type {Number}
  361. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>RED_BITS</code>.
  362. */
  363. redBits : {
  364. get : function() {
  365. return this._redBits;
  366. }
  367. },
  368. /**
  369. * The number of green bits per component in the default framebuffer's color buffer. The minimum is eight.
  370. * @memberof Context.prototype
  371. * @type {Number}
  372. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>GREEN_BITS</code>.
  373. */
  374. greenBits : {
  375. get : function() {
  376. return this._greenBits;
  377. }
  378. },
  379. /**
  380. * The number of blue bits per component in the default framebuffer's color buffer. The minimum is eight.
  381. * @memberof Context.prototype
  382. * @type {Number}
  383. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>BLUE_BITS</code>.
  384. */
  385. blueBits : {
  386. get : function() {
  387. return this._blueBits;
  388. }
  389. },
  390. /**
  391. * The number of alpha bits per component in the default framebuffer's color buffer. The minimum is eight.
  392. * <br /><br />
  393. * The alpha channel is used for GL destination alpha operations and by the HTML compositor to combine the color buffer
  394. * with the rest of the page.
  395. * @memberof Context.prototype
  396. * @type {Number}
  397. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALPHA_BITS</code>.
  398. */
  399. alphaBits : {
  400. get : function() {
  401. return this._alphaBits;
  402. }
  403. },
  404. /**
  405. * The number of depth bits per pixel in the default bound framebuffer. The minimum is 16 bits; most
  406. * implementations will have 24 bits.
  407. * @memberof Context.prototype
  408. * @type {Number}
  409. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>DEPTH_BITS</code>.
  410. */
  411. depthBits : {
  412. get : function() {
  413. return this._depthBits;
  414. }
  415. },
  416. /**
  417. * The number of stencil bits per pixel in the default bound framebuffer. The minimum is eight bits.
  418. * @memberof Context.prototype
  419. * @type {Number}
  420. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>STENCIL_BITS</code>.
  421. */
  422. stencilBits : {
  423. get : function() {
  424. return this._stencilBits;
  425. }
  426. },
  427. /**
  428. * The maximum number of texture units that can be used from the vertex and fragment
  429. * shader with this WebGL implementation. The minimum is eight. If both shaders access the
  430. * same texture unit, this counts as two texture units.
  431. * @memberof Context.prototype
  432. * @type {Number}
  433. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_COMBINED_TEXTURE_IMAGE_UNITS</code>.
  434. */
  435. maximumCombinedTextureImageUnits : {
  436. get : function() {
  437. return this._maximumCombinedTextureImageUnits;
  438. }
  439. },
  440. /**
  441. * The approximate maximum cube mape width and height supported by this WebGL implementation.
  442. * The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.
  443. * @memberof Context.prototype
  444. * @type {Number}
  445. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_CUBE_MAP_TEXTURE_SIZE</code>.
  446. */
  447. maximumCubeMapSize : {
  448. get : function() {
  449. return this._maximumCubeMapSize;
  450. }
  451. },
  452. /**
  453. * The maximum number of <code>vec4</code>, <code>ivec4</code>, and <code>bvec4</code>
  454. * uniforms that can be used by a fragment shader with this WebGL implementation. The minimum is 16.
  455. * @memberof Context.prototype
  456. * @type {Number}
  457. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_FRAGMENT_UNIFORM_VECTORS</code>.
  458. */
  459. maximumFragmentUniformVectors : {
  460. get : function() {
  461. return this._maximumFragmentUniformVectors;
  462. }
  463. },
  464. /**
  465. * The maximum number of texture units that can be used from the fragment shader with this WebGL implementation. The minimum is eight.
  466. * @memberof Context.prototype
  467. * @type {Number}
  468. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_TEXTURE_IMAGE_UNITS</code>.
  469. */
  470. maximumTextureImageUnits : {
  471. get : function() {
  472. return this._maximumTextureImageUnits;
  473. }
  474. },
  475. /**
  476. * The maximum renderbuffer width and height supported by this WebGL implementation.
  477. * The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.
  478. * @memberof Context.prototype
  479. * @type {Number}
  480. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_RENDERBUFFER_SIZE</code>.
  481. */
  482. maximumRenderbufferSize : {
  483. get : function() {
  484. return this._maximumRenderbufferSize;
  485. }
  486. },
  487. /**
  488. * The approximate maximum texture width and height supported by this WebGL implementation.
  489. * The minimum is 64, but most desktop and laptop implementations will support much larger sizes like 8,192.
  490. * @memberof Context.prototype
  491. * @type {Number}
  492. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_TEXTURE_SIZE</code>.
  493. */
  494. maximumTextureSize : {
  495. get : function() {
  496. return this._maximumTextureSize;
  497. }
  498. },
  499. /**
  500. * The maximum number of <code>vec4</code> varying variables supported by this WebGL implementation.
  501. * The minimum is eight. Matrices and arrays count as multiple <code>vec4</code>s.
  502. * @memberof Context.prototype
  503. * @type {Number}
  504. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VARYING_VECTORS</code>.
  505. */
  506. maximumVaryingVectors : {
  507. get : function() {
  508. return this._maximumVaryingVectors;
  509. }
  510. },
  511. /**
  512. * The maximum number of <code>vec4</code> vertex attributes supported by this WebGL implementation. The minimum is eight.
  513. * @memberof Context.prototype
  514. * @type {Number}
  515. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VERTEX_ATTRIBS</code>.
  516. */
  517. maximumVertexAttributes : {
  518. get : function() {
  519. return this._maximumVertexAttributes;
  520. }
  521. },
  522. /**
  523. * The maximum number of texture units that can be used from the vertex shader with this WebGL implementation.
  524. * The minimum is zero, which means the GL does not support vertex texture fetch.
  525. * @memberof Context.prototype
  526. * @type {Number}
  527. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VERTEX_TEXTURE_IMAGE_UNITS</code>.
  528. */
  529. maximumVertexTextureImageUnits : {
  530. get : function() {
  531. return this._maximumVertexTextureImageUnits;
  532. }
  533. },
  534. /**
  535. * The maximum number of <code>vec4</code>, <code>ivec4</code>, and <code>bvec4</code>
  536. * uniforms that can be used by a vertex shader with this WebGL implementation. The minimum is 16.
  537. * @memberof Context.prototype
  538. * @type {Number}
  539. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VERTEX_UNIFORM_VECTORS</code>.
  540. */
  541. maximumVertexUniformVectors : {
  542. get : function() {
  543. return this._maximumVertexUniformVectors;
  544. }
  545. },
  546. /**
  547. * The minimum aliased line width, in pixels, supported by this WebGL implementation. It will be at most one.
  548. * @memberof Context.prototype
  549. * @type {Number}
  550. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_LINE_WIDTH_RANGE</code>.
  551. */
  552. minimumAliasedLineWidth : {
  553. get : function() {
  554. return this._aliasedLineWidthRange[0];
  555. }
  556. },
  557. /**
  558. * The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.
  559. * @memberof Context.prototype
  560. * @type {Number}
  561. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_LINE_WIDTH_RANGE</code>.
  562. */
  563. maximumAliasedLineWidth : {
  564. get : function() {
  565. return this._aliasedLineWidthRange[1];
  566. }
  567. },
  568. /**
  569. * The minimum aliased point size, in pixels, supported by this WebGL implementation. It will be at most one.
  570. * @memberof Context.prototype
  571. * @type {Number}
  572. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_POINT_SIZE_RANGE</code>.
  573. */
  574. minimumAliasedPointSize : {
  575. get : function() {
  576. return this._aliasedPointSizeRange[0];
  577. }
  578. },
  579. /**
  580. * The maximum aliased point size, in pixels, supported by this WebGL implementation. It will be at least one.
  581. * @memberof Context.prototype
  582. * @type {Number}
  583. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_POINT_SIZE_RANGE</code>.
  584. */
  585. maximumAliasedPointSize : {
  586. get : function() {
  587. return this._aliasedPointSizeRange[1];
  588. }
  589. },
  590. /**
  591. * The maximum supported width of the viewport. It will be at least as large as the visible width of the associated canvas.
  592. * @memberof Context.prototype
  593. * @type {Number}
  594. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VIEWPORT_DIMS</code>.
  595. */
  596. maximumViewportWidth : {
  597. get : function() {
  598. return this._maximumViewportDimensions[0];
  599. }
  600. },
  601. /**
  602. * The maximum supported height of the viewport. It will be at least as large as the visible height of the associated canvas.
  603. * @memberof Context.prototype
  604. * @type {Number}
  605. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>MAX_VIEWPORT_DIMS</code>.
  606. */
  607. maximumViewportHeight : {
  608. get : function() {
  609. return this._maximumViewportDimensions[1];
  610. }
  611. },
  612. /**
  613. * <code>true</code> if the WebGL context supports antialiasing. By default
  614. * antialiasing is requested, but it is not supported by all systems.
  615. * @memberof Context.prototype
  616. * @type {Boolean}
  617. */
  618. antialias : {
  619. get : function() {
  620. return this._antialias;
  621. }
  622. },
  623. /**
  624. * <code>true</code> if the OES_standard_derivatives extension is supported. This
  625. * extension provides access to <code>dFdx<code>, <code>dFdy<code>, and <code>fwidth<code>
  626. * functions from GLSL. A shader using these functions still needs to explicitly enable the
  627. * extension with <code>#extension GL_OES_standard_derivatives : enable</code>.
  628. * @memberof Context.prototype
  629. * @type {Boolean}
  630. * @see {@link http://www.khronos.org/registry/gles/extensions/OES/OES_standard_derivatives.txt|OES_standard_derivatives}
  631. */
  632. standardDerivatives : {
  633. get : function() {
  634. return !!this._standardDerivatives;
  635. }
  636. },
  637. /**
  638. * <code>true</code> if the OES_element_index_uint extension is supported. This
  639. * extension allows the use of unsigned int indices, which can improve performance by
  640. * eliminating batch breaking caused by unsigned short indices.
  641. * @memberof Context.prototype
  642. * @type {Boolean}
  643. * @see {@link http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/|OES_element_index_uint}
  644. */
  645. elementIndexUint : {
  646. get : function() {
  647. return !!this._elementIndexUint;
  648. }
  649. },
  650. /**
  651. * <code>true</code> if WEBGL_depth_texture is supported. This extension provides
  652. * access to depth textures that, for example, can be attached to framebuffers for shadow mapping.
  653. * @memberof Context.prototype
  654. * @type {Boolean}
  655. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
  656. */
  657. depthTexture : {
  658. get : function() {
  659. return !!this._depthTexture;
  660. }
  661. },
  662. /**
  663. * <code>true</code> if OES_texture_float is supported. This extension provides
  664. * access to floating point textures that, for example, can be attached to framebuffers for high dynamic range.
  665. * @memberof Context.prototype
  666. * @type {Boolean}
  667. * @see {@link http://www.khronos.org/registry/gles/extensions/OES/OES_texture_float.txt|OES_texture_float}
  668. */
  669. floatingPointTexture : {
  670. get : function() {
  671. return !!this._textureFloat;
  672. }
  673. },
  674. textureFilterAnisotropic : {
  675. get : function() {
  676. return !!this._textureFilterAnisotropic;
  677. }
  678. },
  679. maximumTextureFilterAnisotropy : {
  680. get : function() {
  681. return this._maximumTextureFilterAnisotropy;
  682. }
  683. },
  684. /**
  685. * <code>true</code> if the OES_vertex_array_object extension is supported. This
  686. * extension can improve performance by reducing the overhead of switching vertex arrays.
  687. * When enabled, this extension is automatically used by {@link VertexArray}.
  688. * @memberof Context.prototype
  689. * @type {Boolean}
  690. * @see {@link http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/|OES_vertex_array_object}
  691. */
  692. vertexArrayObject : {
  693. get : function() {
  694. return !!this._vertexArrayObject;
  695. }
  696. },
  697. /**
  698. * <code>true</code> if the EXT_frag_depth extension is supported. This
  699. * extension provides access to the <code>gl_FragDepthEXT<code> built-in output variable
  700. * from GLSL fragment shaders. A shader using these functions still needs to explicitly enable the
  701. * extension with <code>#extension GL_EXT_frag_depth : enable</code>.
  702. * @memberof Context.prototype
  703. * @type {Boolean}
  704. * @see {@link http://www.khronos.org/registry/webgl/extensions/EXT_frag_depth/|EXT_frag_depth}
  705. */
  706. fragmentDepth : {
  707. get : function() {
  708. return !!this._fragDepth;
  709. }
  710. },
  711. /**
  712. * <code>true</code> if the WEBGL_draw_buffers extension is supported. This
  713. * extensions provides support for multiple render targets. The framebuffer object can have mutiple
  714. * color attachments and the GLSL fragment shader can write to the built-in output array <code>gl_FragData</code>.
  715. * A shader using this feature needs to explicitly enable the extension with
  716. * <code>#extension GL_EXT_draw_buffers : enable</code>.
  717. * @memberof Context.prototype
  718. * @type {Boolean}
  719. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_draw_buffers/|WEBGL_draw_buffers}
  720. */
  721. drawBuffers : {
  722. get : function() {
  723. return !!this._drawBuffers;
  724. }
  725. },
  726. /**
  727. * The maximum number of simultaneous outputs that may be written in a fragment shader.
  728. * @memberof Context.prototype
  729. * @type {Number}
  730. */
  731. maximumDrawBuffers : {
  732. get : function() {
  733. return this._maximumDrawBuffers;
  734. }
  735. },
  736. /**
  737. * The maximum number of color attachments supported.
  738. * @memberof Context.prototype
  739. * @type {Number}
  740. */
  741. maximumColorAttachments : {
  742. get : function() {
  743. return this._maximumColorAttachments;
  744. }
  745. },
  746. debugShaders : {
  747. get : function() {
  748. return this._debugShaders;
  749. }
  750. },
  751. throwOnWebGLError : {
  752. get : function() {
  753. return this._throwOnWebGLError;
  754. },
  755. set : function(value) {
  756. this._throwOnWebGLError = value;
  757. this._gl = wrapGL(this._originalGLContext, value ? throwOnError : null);
  758. }
  759. },
  760. /**
  761. * A 1x1 RGBA texture initialized to [255, 255, 255, 255]. This can
  762. * be used as a placeholder texture while other textures are downloaded.
  763. * @memberof Context.prototype
  764. * @type {Texture}
  765. */
  766. defaultTexture : {
  767. get : function() {
  768. if (this._defaultTexture === undefined) {
  769. this._defaultTexture = this.createTexture2D({
  770. source : {
  771. width : 1,
  772. height : 1,
  773. arrayBufferView : new Uint8Array([255, 255, 255, 255])
  774. }
  775. });
  776. }
  777. return this._defaultTexture;
  778. }
  779. },
  780. /**
  781. * A cube map, where each face is a 1x1 RGBA texture initialized to
  782. * [255, 255, 255, 255]. This can be used as a placeholder cube map while
  783. * other cube maps are downloaded.
  784. * @memberof Context.prototype
  785. * @type {CubeMap}
  786. */
  787. defaultCubeMap : {
  788. get : function() {
  789. if (this._defaultCubeMap === undefined) {
  790. var face = {
  791. width : 1,
  792. height : 1,
  793. arrayBufferView : new Uint8Array([255, 255, 255, 255])
  794. };
  795. this._defaultCubeMap = this.createCubeMap({
  796. source : {
  797. positiveX : face,
  798. negativeX : face,
  799. positiveY : face,
  800. negativeY : face,
  801. positiveZ : face,
  802. negativeZ : face
  803. }
  804. });
  805. }
  806. return this._defaultCubeMap;
  807. }
  808. },
  809. /**
  810. * The drawingBufferWidth of the underlying GL context.
  811. * @memberof Context.prototype
  812. * @type {Number}
  813. * @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferWidth|drawingBufferWidth}
  814. */
  815. drawingBufferHeight : {
  816. get : function() {
  817. return this._gl.drawingBufferHeight;
  818. }
  819. },
  820. /**
  821. * The drawingBufferHeight of the underlying GL context.
  822. * @memberof Context.prototype
  823. * @type {Number}
  824. * @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
  825. */
  826. drawingBufferWidth : {
  827. get : function() {
  828. return this._gl.drawingBufferWidth;
  829. }
  830. },
  831. /**
  832. * Gets an object representing the currently bound framebuffer. While this instance is not an actual
  833. * {@link Framebuffer}, it is used to represent the default framebuffer in calls to
  834. * {@link Context.createTexture2DFromFramebuffer}.
  835. * @memberof Context.prototype
  836. * @type {Object}
  837. */
  838. defaultFramebuffer : {
  839. get : function() {
  840. return defaultFramebufferMarker;
  841. }
  842. }
  843. });
  844. Context.prototype.replaceShaderProgram = function(shaderProgram, vertexShaderSource, fragmentShaderSource, attributeLocations) {
  845. return this._shaderCache.replaceShaderProgram(shaderProgram, vertexShaderSource, fragmentShaderSource, attributeLocations);
  846. };
  847. Context.prototype.createShaderProgram = function(vertexShaderSource, fragmentShaderSource, attributeLocations) {
  848. return this._shaderCache.getShaderProgram(vertexShaderSource, fragmentShaderSource, attributeLocations);
  849. };
  850. function createBuffer(gl, bufferTarget, typedArrayOrSizeInBytes, usage) {
  851. var sizeInBytes;
  852. if (typeof typedArrayOrSizeInBytes === 'number') {
  853. sizeInBytes = typedArrayOrSizeInBytes;
  854. } else if (typeof typedArrayOrSizeInBytes === 'object' && typeof typedArrayOrSizeInBytes.byteLength === 'number') {
  855. sizeInBytes = typedArrayOrSizeInBytes.byteLength;
  856. } else {
  857. //>>includeStart('debug', pragmas.debug);
  858. throw new DeveloperError('typedArrayOrSizeInBytes must be either a typed array or a number.');
  859. //>>includeEnd('debug');
  860. }
  861. //>>includeStart('debug', pragmas.debug);
  862. if (sizeInBytes <= 0) {
  863. throw new DeveloperError('typedArrayOrSizeInBytes must be greater than zero.');
  864. }
  865. if (!BufferUsage.validate(usage)) {
  866. throw new DeveloperError('usage is invalid.');
  867. }
  868. //>>includeEnd('debug');
  869. var buffer = gl.createBuffer();
  870. gl.bindBuffer(bufferTarget, buffer);
  871. gl.bufferData(bufferTarget, typedArrayOrSizeInBytes, usage);
  872. gl.bindBuffer(bufferTarget, null);
  873. return new Buffer(gl, bufferTarget, sizeInBytes, usage, buffer);
  874. }
  875. /**
  876. * Creates a vertex buffer, which contains untyped vertex data in GPU-controlled memory.
  877. * <br /><br />
  878. * A vertex array defines the actual makeup of a vertex, e.g., positions, normals, texture coordinates,
  879. * etc., by interpreting the raw data in one or more vertex buffers.
  880. *
  881. * @param {ArrayBufferView|Number} typedArrayOrSizeInBytes A typed array containing the data to copy to the buffer, or a <code>Number</code> defining the size of the buffer in bytes.
  882. * @param {BufferUsage} usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}.
  883. * @returns {VertexBuffer} The vertex buffer, ready to be attached to a vertex array.
  884. *
  885. * @exception {DeveloperError} The size in bytes must be greater than zero.
  886. * @exception {DeveloperError} Invalid <code>usage</code>.
  887. *
  888. * @see Context#createVertexArray
  889. * @see Context#createIndexBuffer
  890. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer}
  891. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with <code>ARRAY_BUFFER</code>
  892. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with <code>ARRAY_BUFFER</code>
  893. *
  894. * @example
  895. * // Example 1. Create a dynamic vertex buffer 16 bytes in size.
  896. * var buffer = context.createVertexBuffer(16, BufferUsage.DYNAMIC_DRAW);
  897. *
  898. * @example
  899. * // Example 2. Create a dynamic vertex buffer from three floating-point values.
  900. * // The data copied to the vertex buffer is considered raw bytes until it is
  901. * // interpreted as vertices using a vertex array.
  902. * var positionBuffer = context.createVertexBuffer(new Float32Array([0, 0, 0]),
  903. * BufferUsage.STATIC_DRAW);
  904. */
  905. Context.prototype.createVertexBuffer = function(typedArrayOrSizeInBytes, usage) {
  906. return createBuffer(this._gl, this._gl.ARRAY_BUFFER, typedArrayOrSizeInBytes, usage);
  907. };
  908. /**
  909. * Creates an index buffer, which contains typed indices in GPU-controlled memory.
  910. * <br /><br />
  911. * An index buffer can be attached to a vertex array to select vertices for rendering.
  912. * <code>Context.draw</code> can render using the entire index buffer or a subset
  913. * of the index buffer defined by an offset and count.
  914. *
  915. * @param {ArrayBufferView|Number} typedArrayOrSizeInBytes A typed array containing the data to copy to the buffer, or a <code>Number</code> defining the size of the buffer in bytes.
  916. * @param {BufferUsage} usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}.
  917. * @param {IndexDatatype} indexDatatype The datatype of indices in the buffer.
  918. * @returns {IndexBuffer} The index buffer, ready to be attached to a vertex array.
  919. *
  920. * @exception {DeveloperError} IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint.
  921. * @exception {DeveloperError} The size in bytes must be greater than zero.
  922. * @exception {DeveloperError} Invalid <code>usage</code>.
  923. * @exception {DeveloperError} Invalid <code>indexDatatype</code>.
  924. *
  925. * @see Context#createVertexArray
  926. * @see Context#createVertexBuffer
  927. * @see Context#draw
  928. * @see VertexArray
  929. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer}
  930. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with <code>ELEMENT_ARRAY_BUFFER</code>
  931. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with <code>ELEMENT_ARRAY_BUFFER</code>
  932. *
  933. * @example
  934. * // Example 1. Create a stream index buffer of unsigned shorts that is
  935. * // 16 bytes in size.
  936. * var buffer = context.createIndexBuffer(16, BufferUsage.STREAM_DRAW,
  937. * IndexDatatype.UNSIGNED_SHORT);
  938. *
  939. * @example
  940. * // Example 2. Create a static index buffer containing three unsigned shorts.
  941. * var buffer = context.createIndexBuffer(new Uint16Array([0, 1, 2]),
  942. * BufferUsage.STATIC_DRAW, IndexDatatype.UNSIGNED_SHORT)
  943. */
  944. Context.prototype.createIndexBuffer = function(typedArrayOrSizeInBytes, usage, indexDatatype) {
  945. //>>includeStart('debug', pragmas.debug);
  946. if (!IndexDatatype.validate(indexDatatype)) {
  947. throw new DeveloperError('Invalid indexDatatype.');
  948. }
  949. //>>includeEnd('debug');
  950. if ((indexDatatype === IndexDatatype.UNSIGNED_INT) && !this.elementIndexUint) {
  951. throw new DeveloperError('IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint.');
  952. }
  953. var bytesPerIndex = IndexDatatype.getSizeInBytes(indexDatatype);
  954. var gl = this._gl;
  955. var buffer = createBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, typedArrayOrSizeInBytes, usage);
  956. var numberOfIndices = buffer.sizeInBytes / bytesPerIndex;
  957. defineProperties(buffer, {
  958. indexDatatype: {
  959. get : function() {
  960. return indexDatatype;
  961. }
  962. },
  963. bytesPerIndex : {
  964. get : function() {
  965. return bytesPerIndex;
  966. }
  967. },
  968. numberOfIndices : {
  969. get : function() {
  970. return numberOfIndices;
  971. }
  972. }
  973. });
  974. return buffer;
  975. };
  976. /**
  977. * Creates a vertex array, which defines the attributes making up a vertex, and contains an optional index buffer
  978. * to select vertices for rendering. Attributes are defined using object literals as shown in Example 1 below.
  979. *
  980. * @param {Object[]} [attributes] An optional array of attributes.
  981. * @param {IndexBuffer} [indexBuffer] An optional index buffer.
  982. *
  983. * @returns {VertexArray} The vertex array, ready for use with drawing.
  984. *
  985. * @exception {DeveloperError} Attribute must have a <code>vertexBuffer</code>.
  986. * @exception {DeveloperError} Attribute must have a <code>componentsPerAttribute</code>.
  987. * @exception {DeveloperError} Attribute must have a valid <code>componentDatatype</code> or not specify it.
  988. * @exception {DeveloperError} Attribute must have a <code>strideInBytes</code> less than or equal to 255 or not specify it.
  989. * @exception {DeveloperError} Index n is used by more than one attribute.
  990. *
  991. * @see Context#createVertexArrayFromGeometry
  992. * @see Context#createVertexBuffer
  993. * @see Context#createIndexBuffer
  994. * @see Context#draw
  995. *
  996. * @example
  997. * // Example 1. Create a vertex array with vertices made up of three floating point
  998. * // values, e.g., a position, from a single vertex buffer. No index buffer is used.
  999. * var positionBuffer = context.createVertexBuffer(12, BufferUsage.STATIC_DRAW);
  1000. * var attributes = [
  1001. * {
  1002. * index : 0,
  1003. * enabled : true,
  1004. * vertexBuffer : positionBuffer,
  1005. * componentsPerAttribute : 3,
  1006. * componentDatatype : ComponentDatatype.FLOAT,
  1007. * normalize : false,
  1008. * offsetInBytes : 0,
  1009. * strideInBytes : 0 // tightly packed
  1010. * }
  1011. * ];
  1012. * var va = context.createVertexArray(attributes);
  1013. *
  1014. * @example
  1015. * // Example 2. Create a vertex array with vertices from two different vertex buffers.
  1016. * // Each vertex has a three-component position and three-component normal.
  1017. * var positionBuffer = context.createVertexBuffer(12, BufferUsage.STATIC_DRAW);
  1018. * var normalBuffer = context.createVertexBuffer(12, BufferUsage.STATIC_DRAW);
  1019. * var attributes = [
  1020. * {
  1021. * index : 0,
  1022. * vertexBuffer : positionBuffer,
  1023. * componentsPerAttribute : 3,
  1024. * componentDatatype : ComponentDatatype.FLOAT
  1025. * },
  1026. * {
  1027. * index : 1,
  1028. * vertexBuffer : normalBuffer,
  1029. * componentsPerAttribute : 3,
  1030. * componentDatatype : ComponentDatatype.FLOAT
  1031. * }
  1032. * ];
  1033. * var va = context.createVertexArray(attributes);
  1034. *
  1035. * @example
  1036. * // Example 3. Creates the same vertex layout as Example 2 using a single
  1037. * // vertex buffer, instead of two.
  1038. * var buffer = context.createVertexBuffer(24, BufferUsage.STATIC_DRAW);
  1039. * var attributes = [
  1040. * {
  1041. * vertexBuffer : buffer,
  1042. * componentsPerAttribute : 3,
  1043. * componentDatatype : ComponentDatatype.FLOAT,
  1044. * offsetInBytes : 0,
  1045. * strideInBytes : 24
  1046. * },
  1047. * {
  1048. * vertexBuffer : buffer,
  1049. * componentsPerAttribute : 3,
  1050. * componentDatatype : ComponentDatatype.FLOAT,
  1051. * normalize : true,
  1052. * offsetInBytes : 12,
  1053. * strideInBytes : 24
  1054. * }
  1055. * ];
  1056. * var va = context.createVertexArray(attributes);
  1057. */
  1058. Context.prototype.createVertexArray = function(attributes, indexBuffer) {
  1059. return new VertexArray(this._gl, this._vertexArrayObject, attributes, indexBuffer);
  1060. };
  1061. /**
  1062. * options.source can be {@link ImageData}, {@link Image}, {@link Canvas}, or {@link Video}.
  1063. *
  1064. * @exception {RuntimeError} When options.pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, this WebGL implementation must support WEBGL_depth_texture. Check context.depthTexture.
  1065. * @exception {RuntimeError} When options.pixelDatatype is FLOAT, this WebGL implementation must support the OES_texture_float extension. Check context.floatingPointTexture.
  1066. * @exception {DeveloperError} options requires a source field to create an initialized texture or width and height fields to create a blank texture.
  1067. * @exception {DeveloperError} Width must be greater than zero.
  1068. * @exception {DeveloperError} Width must be less than or equal to the maximum texture size.
  1069. * @exception {DeveloperError} Height must be greater than zero.
  1070. * @exception {DeveloperError} Height must be less than or equal to the maximum texture size.
  1071. * @exception {DeveloperError} Invalid options.pixelFormat.
  1072. * @exception {DeveloperError} Invalid options.pixelDatatype.
  1073. * @exception {DeveloperError} When options.pixelFormat is DEPTH_COMPONENT, options.pixelDatatype must be UNSIGNED_SHORT or UNSIGNED_INT.
  1074. * @exception {DeveloperError} When options.pixelFormat is DEPTH_STENCIL, options.pixelDatatype must be UNSIGNED_INT_24_8_WEBGL.
  1075. * @exception {DeveloperError} When options.pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, source cannot be provided.
  1076. *
  1077. * @see Context#createTexture2DFromFramebuffer
  1078. * @see Context#createCubeMap
  1079. * @see Context#createSampler
  1080. */
  1081. Context.prototype.createTexture2D = function(options) {
  1082. return new Texture(this, options);
  1083. };
  1084. /**
  1085. * Creates a texture, and copies a subimage of the framebuffer to it. When called without arguments,
  1086. * the texture is the same width and height as the framebuffer and contains its contents.
  1087. *
  1088. * @param {PixelFormat} [pixelFormat=PixelFormat.RGB] The texture's internal pixel format.
  1089. * @param {Number} [framebufferXOffset=0] An offset in the x direction in the framebuffer where copying begins from.
  1090. * @param {Number} [framebufferYOffset=0] An offset in the y direction in the framebuffer where copying begins from.
  1091. * @param {Number} [width=canvas.clientWidth] The width of the texture in texels.
  1092. * @param {Number} [height=canvas.clientHeight] The height of the texture in texels.
  1093. * @param {Framebuffer} [framebuffer=defaultFramebuffer] The framebuffer from which to create the texture. If this
  1094. * parameter is not specified, the default framebuffer is used.
  1095. * @returns {Texture} A texture with contents from the framebuffer.
  1096. *
  1097. * @exception {DeveloperError} Invalid pixelFormat.
  1098. * @exception {DeveloperError} pixelFormat cannot be DEPTH_COMPONENT or DEPTH_STENCIL.
  1099. * @exception {DeveloperError} framebufferXOffset must be greater than or equal to zero.
  1100. * @exception {DeveloperError} framebufferYOffset must be greater than or equal to zero.
  1101. * @exception {DeveloperError} framebufferXOffset + width must be less than or equal to canvas.clientWidth.
  1102. * @exception {DeveloperError} framebufferYOffset + height must be less than or equal to canvas.clientHeight.
  1103. *
  1104. * @see Context#createTexture2D
  1105. * @see Context#createCubeMap
  1106. * @see Context#createSampler
  1107. *
  1108. * @example
  1109. * // Create a texture with the contents of the framebuffer.
  1110. * var t = context.createTexture2DFromFramebuffer();
  1111. */
  1112. Context.prototype.createTexture2DFromFramebuffer = function(pixelFormat, framebufferXOffset, framebufferYOffset, width, height, framebuffer) {
  1113. var gl = this._gl;
  1114. pixelFormat = defaultValue(pixelFormat, PixelFormat.RGB);
  1115. framebufferXOffset = defaultValue(framebufferXOffset, 0);
  1116. framebufferYOffset = defaultValue(framebufferYOffset, 0);
  1117. width = defaultValue(width, gl.drawingBufferWidth);
  1118. height = defaultValue(height, gl.drawingBufferHeight);
  1119. //>>includeStart('debug', pragmas.debug);
  1120. if (!PixelFormat.validate(pixelFormat)) {
  1121. throw new DeveloperError('Invalid pixelFormat.');
  1122. }
  1123. if (PixelFormat.isDepthFormat(pixelFormat)) {
  1124. throw new DeveloperError('pixelFormat cannot be DEPTH_COMPONENT or DEPTH_STENCIL.');
  1125. }
  1126. if (framebufferXOffset < 0) {
  1127. throw new DeveloperError('framebufferXOffset must be greater than or equal to zero.');
  1128. }
  1129. if (framebufferYOffset < 0) {
  1130. throw new DeveloperError('framebufferYOffset must be greater than or equal to zero.');
  1131. }
  1132. if (framebufferXOffset + width > gl.drawingBufferWidth) {
  1133. throw new DeveloperError('framebufferXOffset + width must be less than or equal to drawingBufferWidth');
  1134. }
  1135. if (framebufferYOffset + height > gl.drawingBufferHeight) {
  1136. throw new DeveloperError('framebufferYOffset + height must be less than or equal to drawingBufferHeight.');
  1137. }
  1138. //>>includeEnd('debug');
  1139. var texture = new Texture(this, {
  1140. width : width,
  1141. height : height,
  1142. pixelFormat : pixelFormat,
  1143. source : {
  1144. framebuffer : defined(framebuffer) ? framebuffer : this.defaultFramebuffer,
  1145. xOffset : framebufferXOffset,
  1146. yOffset : framebufferYOffset,
  1147. width : width,
  1148. height : height
  1149. }
  1150. });
  1151. return texture;
  1152. };
  1153. /**
  1154. * options.source can be {@link ImageData}, {@link Image}, {@link Canvas}, or {@link Video}.
  1155. *
  1156. * @returns {CubeMap} The newly created cube map.
  1157. *
  1158. * @exception {RuntimeError} When options.pixelDatatype is FLOAT, this WebGL implementation must support the OES_texture_float extension. Check context.floatingPointTexture.
  1159. * @exception {DeveloperError} options.source requires positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ faces.
  1160. * @exception {DeveloperError} Each face in options.sources must have the same width and height.
  1161. * @exception {DeveloperError} options requires a source field to create an initialized cube map or width and height fields to create a blank cube map.
  1162. * @exception {DeveloperError} Width must equal height.
  1163. * @exception {DeveloperError} Width and height must be greater than zero.
  1164. * @exception {DeveloperError} Width and height must be less than or equal to the maximum cube map size.
  1165. * @exception {DeveloperError} Invalid options.pixelFormat.
  1166. * @exception {DeveloperError} options.pixelFormat cannot be DEPTH_COMPONENT or DEPTH_STENCIL.
  1167. * @exception {DeveloperError} Invalid options.pixelDatatype.
  1168. *
  1169. * @see Context#createTexture2D
  1170. * @see Context#createTexture2DFromFramebuffer
  1171. * @see Context#createSampler
  1172. */
  1173. Context.prototype.createCubeMap = function(options) {
  1174. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  1175. var source = options.source;
  1176. var width;
  1177. var height;
  1178. if (defined(source)) {
  1179. var faces = [source.positiveX, source.negativeX, source.positiveY, source.negativeY, source.positiveZ, source.negativeZ];
  1180. //>>includeStart('debug', pragmas.debug);
  1181. if (!faces[0] || !faces[1] || !faces[2] || !faces[3] || !faces[4] || !faces[5]) {
  1182. throw new DeveloperError('options.source requires positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ faces.');
  1183. }
  1184. //>>includeEnd('debug');
  1185. width = faces[0].width;
  1186. height = faces[0].height;
  1187. //>>includeStart('debug', pragmas.debug);
  1188. for ( var i = 1; i < 6; ++i) {
  1189. if ((Number(faces[i].width) !== width) || (Number(faces[i].height) !== height)) {
  1190. throw new DeveloperError('Each face in options.source must have the same width and height.');
  1191. }
  1192. }
  1193. //>>includeEnd('debug');
  1194. } else {
  1195. width = options.width;
  1196. height = options.height;
  1197. }
  1198. var size = width;
  1199. var pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGBA);
  1200. var pixelDatatype = defaultValue(options.pixelDatatype, PixelDatatype.UNSIGNED_BYTE);
  1201. //>>includeStart('debug', pragmas.debug);
  1202. if (!defined(width) || !defined(height)) {
  1203. throw new DeveloperError('options requires a source field to create an initialized cube map or width and height fields to create a blank cube map.');
  1204. }
  1205. if (width !== height) {
  1206. throw new DeveloperError('Width must equal height.');
  1207. }
  1208. if (size <= 0) {
  1209. throw new DeveloperError('Width and height must be greater than zero.');
  1210. }
  1211. if (size > this._maximumCubeMapSize) {
  1212. throw new DeveloperError('Width and height must be less than or equal to the maximum cube map size (' + this._maximumCubeMapSize + '). Check maximumCubeMapSize.');
  1213. }
  1214. if (!PixelFormat.validate(pixelFormat)) {
  1215. throw new DeveloperError('Invalid options.pixelFormat.');
  1216. }
  1217. if (PixelFormat.isDepthFormat(pixelFormat)) {
  1218. throw new DeveloperError('options.pixelFormat cannot be DEPTH_COMPONENT or DEPTH_STENCIL.');
  1219. }
  1220. if (!PixelDatatype.validate(pixelDatatype)) {
  1221. throw new DeveloperError('Invalid options.pixelDatatype.');
  1222. }
  1223. //>>includeEnd('debug');
  1224. if ((pixelDatatype === PixelDatatype.FLOAT) && !this.floatingPointTexture) {
  1225. throw new DeveloperError('When options.pixelDatatype is FLOAT, this WebGL implementation must support the OES_texture_float extension.');
  1226. }
  1227. // Use premultiplied alpha for opaque textures should perform better on Chrome:
  1228. // http://media.tojicode.com/webglCamp4/#20
  1229. var preMultiplyAlpha = options.preMultiplyAlpha || ((pixelFormat === PixelFormat.RGB) || (pixelFormat === PixelFormat.LUMINANCE));
  1230. var flipY = defaultValue(options.flipY, true);
  1231. var gl = this._gl;
  1232. var textureTarget = gl.TEXTURE_CUBE_MAP;
  1233. var texture = gl.createTexture();
  1234. gl.activeTexture(gl.TEXTURE0);
  1235. gl.bindTexture(textureTarget, texture);
  1236. function createFace(target, sourceFace) {
  1237. if (sourceFace.arrayBufferView) {
  1238. gl.texImage2D(target, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, sourceFace.arrayBufferView);
  1239. } else {
  1240. gl.texImage2D(target, 0, pixelFormat, pixelFormat, pixelDatatype, sourceFace);
  1241. }
  1242. }
  1243. if (defined(source)) {
  1244. // TODO: _gl.pixelStorei(_gl._UNPACK_ALIGNMENT, 4);
  1245. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
  1246. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
  1247. createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_X, source.positiveX);
  1248. createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, source.negativeX);
  1249. createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, source.positiveY);
  1250. createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, source.negativeY);
  1251. createFace(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, source.positiveZ);
  1252. createFace(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, source.negativeZ);
  1253. } else {
  1254. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1255. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1256. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1257. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1258. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1259. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, pixelFormat, size, size, 0, pixelFormat, pixelDatatype, null);
  1260. }
  1261. gl.bindTexture(textureTarget, null);
  1262. return new CubeMap(gl, this._textureFilterAnisotropic, textureTarget, texture, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY);
  1263. };
  1264. /**
  1265. * Creates a framebuffer with optional initial color, depth, and stencil attachments.
  1266. * Framebuffers are used for render-to-texture effects; they allow us to render to
  1267. * textures in one pass, and read from it in a later pass.
  1268. *
  1269. * @param {Object} [options] The initial framebuffer attachments as shown in the examplebelow. The possible properties are <code>colorTextures</code>, <code>colorRenderbuffers</code>, <code>depthTexture</code>, <code>depthRenderbuffer</code>, <code>stencilRenderbuffer</code>, <code>depthStencilTexture</code>, and <code>depthStencilRenderbuffer</code>.
  1270. * @returns {Framebuffer} The created framebuffer.
  1271. *
  1272. * @exception {DeveloperError} Cannot have both color texture and color renderbuffer attachments.
  1273. * @exception {DeveloperError} Cannot have both a depth texture and depth renderbuffer attachment.
  1274. * @exception {DeveloperError} Cannot have both a depth-stencil texture and depth-stencil renderbuffer attachment.
  1275. * @exception {DeveloperError} Cannot have both a depth and depth-stencil renderbuffer.
  1276. * @exception {DeveloperError} Cannot have both a stencil and depth-stencil renderbuffer.
  1277. * @exception {DeveloperError} Cannot have both a depth and stencil renderbuffer.
  1278. * @exception {DeveloperError} The color-texture pixel-format must be a color format.
  1279. * @exception {DeveloperError} The depth-texture pixel-format must be DEPTH_COMPONENT.
  1280. * @exception {DeveloperError} The depth-stencil-texture pixel-format must be DEPTH_STENCIL.
  1281. * @exception {DeveloperError} The number of color attachments exceeds the number supported.
  1282. *
  1283. * @see Context#createTexture2D
  1284. * @see Context#createCubeMap
  1285. * @see Context#createRenderbuffer
  1286. *
  1287. * @example
  1288. * // Create a framebuffer with color and depth texture attachments.
  1289. * var width = context.canvas.clientWidth;
  1290. * var height = context.canvas.clientHeight;
  1291. * var framebuffer = context.createFramebuffer({
  1292. * colorTextures : [context.createTexture2D({
  1293. * width : width,
  1294. * height : height,
  1295. * pixelFormat : PixelFormat.RGBA
  1296. * })],
  1297. * depthTexture : context.createTexture2D({
  1298. * width : width,
  1299. * height : height,
  1300. * pixelFormat : PixelFormat.DEPTH_COMPONENT,
  1301. * pixelDatatype : PixelDatatype.UNSIGNED_SHORT
  1302. * })
  1303. * });
  1304. */
  1305. Context.prototype.createFramebuffer = function(options) {
  1306. return new Framebuffer(this._gl, this._maximumColorAttachments, options);
  1307. };
  1308. Context.prototype.createRenderbuffer = function(options) {
  1309. var gl = this._gl;
  1310. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  1311. var format = defaultValue(options.format, RenderbufferFormat.RGBA4);
  1312. var width = defined(options.width) ? options.width : gl.drawingBufferWidth;
  1313. var height = defined(options.height) ? options.height : gl.drawingBufferHeight;
  1314. //>>includeStart('debug', pragmas.debug);
  1315. if (!RenderbufferFormat.validate(format)) {
  1316. throw new DeveloperError('Invalid format.');
  1317. }
  1318. if (width <= 0) {
  1319. throw new DeveloperError('Width must be greater than zero.');
  1320. }
  1321. if (width > this.maximumRenderbufferSize) {
  1322. throw new DeveloperError('Width must be less than or equal to the maximum renderbuffer size (' + this.maximumRenderbufferSize + '). Check maximumRenderbufferSize.');
  1323. }
  1324. if (height <= 0) {
  1325. throw new DeveloperError('Height must be greater than zero.');
  1326. }
  1327. if (height > this.maximumRenderbufferSize) {
  1328. throw new DeveloperError('Height must be less than or equal to the maximum renderbuffer size (' + this.maximumRenderbufferSize + '). Check maximumRenderbufferSize.');
  1329. }
  1330. //>>includeEnd('debug');
  1331. return new Renderbuffer(gl, format, width, height);
  1332. };
  1333. var nextRenderStateId = 0;
  1334. var renderStateCache = {};
  1335. /**
  1336. * Validates and then finds or creates an immutable render state, which defines the pipeline
  1337. * state for a {@link DrawCommand} or {@link ClearCommand}. All inputs states are optional. Omitted states
  1338. * use the defaults shown in the example below.
  1339. *
  1340. * @param {Object} [renderState] The states defining the render state as shown in the example below.
  1341. *
  1342. * @exception {RuntimeError} renderState.lineWidth is out of range.
  1343. * @exception {DeveloperError} Invalid renderState.frontFace.
  1344. * @exception {DeveloperError} Invalid renderState.cull.face.
  1345. * @exception {DeveloperError} scissorTest.rectangle.width and scissorTest.rectangle.height must be greater than or equal to zero.
  1346. * @exception {DeveloperError} renderState.depthRange.near can't be greater than renderState.depthRange.far.
  1347. * @exception {DeveloperError} renderState.depthRange.near must be greater than or equal to zero.
  1348. * @exception {DeveloperError} renderState.depthRange.far must be less than or equal to zero.
  1349. * @exception {DeveloperError} Invalid renderState.depthTest.func.
  1350. * @exception {DeveloperError} renderState.blending.color components must be greater than or equal to zero and less than or equal to one
  1351. * @exception {DeveloperError} Invalid renderState.blending.equationRgb.
  1352. * @exception {DeveloperError} Invalid renderState.blending.equationAlpha.
  1353. * @exception {DeveloperError} Invalid renderState.blending.functionSourceRgb.
  1354. * @exception {DeveloperError} Invalid renderState.blending.functionSourceAlpha.
  1355. * @exception {DeveloperError} Invalid renderState.blending.functionDestinationRgb.
  1356. * @exception {DeveloperError} Invalid renderState.blending.functionDestinationAlpha.
  1357. * @exception {DeveloperError} Invalid renderState.stencilTest.frontFunction.
  1358. * @exception {DeveloperError} Invalid renderState.stencilTest.backFunction.
  1359. * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.fail.
  1360. * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.zFail.
  1361. * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.zPass.
  1362. * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.fail.
  1363. * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.zFail.
  1364. * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.zPass.
  1365. * @exception {DeveloperError} renderState.viewport.width must be greater than or equal to zero.
  1366. * @exception {DeveloperError} renderState.viewport.width must be less than or equal to the maximum viewport width.
  1367. * @exception {DeveloperError} renderState.viewport.height must be greater than or equal to zero.
  1368. * @exception {DeveloperError} renderState.viewport.height must be less than or equal to the maximum viewport height.
  1369. *
  1370. * @see DrawCommand
  1371. * @see ClearCommand
  1372. *
  1373. * @example
  1374. * var defaults = {
  1375. * frontFace : WindingOrder.COUNTER_CLOCKWISE,
  1376. * cull : {
  1377. * enabled : false,
  1378. * face : CullFace.BACK
  1379. * },
  1380. * lineWidth : 1,
  1381. * polygonOffset : {
  1382. * enabled : false,
  1383. * factor : 0,
  1384. * units : 0
  1385. * },
  1386. * scissorTest : {
  1387. * enabled : false,
  1388. * rectangle : {
  1389. * x : 0,
  1390. * y : 0,
  1391. * width : 0,
  1392. * height : 0
  1393. * }
  1394. * },
  1395. * depthRange : {
  1396. * near : 0,
  1397. * far : 1
  1398. * },
  1399. * depthTest : {
  1400. * enabled : false,
  1401. * func : DepthFunction.LESS
  1402. * },
  1403. * colorMask : {
  1404. * red : true,
  1405. * green : true,
  1406. * blue : true,
  1407. * alpha : true
  1408. * },
  1409. * depthMask : true,
  1410. * stencilMask : ~0,
  1411. * blending : {
  1412. * enabled : false,
  1413. * color : {
  1414. * red : 0.0,
  1415. * green : 0.0,
  1416. * blue : 0.0,
  1417. * alpha : 0.0
  1418. * },
  1419. * equationRgb : BlendEquation.ADD,
  1420. * equationAlpha : BlendEquation.ADD,
  1421. * functionSourceRgb : BlendFunction.ONE,
  1422. * functionSourceAlpha : BlendFunction.ONE,
  1423. * functionDestinationRgb : BlendFunction.ZERO,
  1424. * functionDestinationAlpha : BlendFunction.ZERO
  1425. * },
  1426. * stencilTest : {
  1427. * enabled : false,
  1428. * frontFunction : StencilFunction.ALWAYS,
  1429. * backFunction : StencilFunction.ALWAYS,
  1430. * reference : 0,
  1431. * mask : ~0,
  1432. * frontOperation : {
  1433. * fail : StencilOperation.KEEP,
  1434. * zFail : StencilOperation.KEEP,
  1435. * zPass : StencilOperation.KEEP
  1436. * },
  1437. * backOperation : {
  1438. * fail : StencilOperation.KEEP,
  1439. * zFail : StencilOperation.KEEP,
  1440. * zPass : StencilOperation.KEEP
  1441. * }
  1442. * },
  1443. * sampleCoverage : {
  1444. * enabled : false,
  1445. * value : 1.0,
  1446. * invert : false
  1447. * }
  1448. * };
  1449. *
  1450. * // Same as just context.createRenderState().
  1451. * var rs = context.createRenderState(defaults);
  1452. */
  1453. Context.prototype.createRenderState = function(renderState) {
  1454. var partialKey = JSON.stringify(renderState);
  1455. var cachedState = renderStateCache[partialKey];
  1456. if (defined(cachedState)) {
  1457. return cachedState;
  1458. }
  1459. // Cache miss. Fully define render state and try again.
  1460. var states = new RenderState(this, renderState);
  1461. var fullKey = JSON.stringify(states);
  1462. cachedState = renderStateCache[fullKey];
  1463. if (!defined(cachedState)) {
  1464. states.id = nextRenderStateId++;
  1465. cachedState = states;
  1466. // Cache full render state. Multiple partially defined render states may map to this.
  1467. renderStateCache[fullKey] = cachedState;
  1468. }
  1469. // Cache partial render state so we can skip validation on a cache hit for a partially defined render state
  1470. renderStateCache[partialKey] = cachedState;
  1471. return cachedState;
  1472. };
  1473. Context.prototype.createSampler = function(sampler) {
  1474. var s = {
  1475. wrapS : defaultValue(sampler.wrapS, TextureWrap.CLAMP_TO_EDGE),
  1476. wrapT : defaultValue(sampler.wrapT, TextureWrap.CLAMP_TO_EDGE),
  1477. minificationFilter : defaultValue(sampler.minificationFilter, TextureMinificationFilter.LINEAR),
  1478. magnificationFilter : defaultValue(sampler.magnificationFilter, TextureMagnificationFilter.LINEAR),
  1479. maximumAnisotropy : (defined(sampler.maximumAnisotropy)) ? sampler.maximumAnisotropy : 1.0
  1480. };
  1481. //>>includeStart('debug', pragmas.debug);
  1482. if (!TextureWrap.validate(s.wrapS)) {
  1483. throw new DeveloperError('Invalid sampler.wrapS.');
  1484. }
  1485. if (!TextureWrap.validate(s.wrapT)) {
  1486. throw new DeveloperError('Invalid sampler.wrapT.');
  1487. }
  1488. if (!TextureMinificationFilter.validate(s.minificationFilter)) {
  1489. throw new DeveloperError('Invalid sampler.minificationFilter.');
  1490. }
  1491. if (!TextureMagnificationFilter.validate(s.magnificationFilter)) {
  1492. throw new DeveloperError('Invalid sampler.magnificationFilter.');
  1493. }
  1494. if (s.maximumAnisotropy < 1.0) {
  1495. throw new DeveloperError('sampler.maximumAnisotropy must be greater than or equal to one.');
  1496. }
  1497. //>>includeEnd('debug');
  1498. return s;
  1499. };
  1500. function validateFramebuffer(context, framebuffer) {
  1501. if (context.validateFramebuffer) {
  1502. var gl = context._gl;
  1503. var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  1504. if (status !== gl.FRAMEBUFFER_COMPLETE) {
  1505. var message;
  1506. switch (status) {
  1507. case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  1508. message = 'Framebuffer is not complete. Incomplete attachment: at least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero, or the color attachment point has a non-color-renderable image attached, or the depth attachment point has a non-depth-renderable image attached, or the stencil attachment point has a non-stencil-renderable image attached. Color-renderable formats include GL_RGBA4, GL_RGB5_A1, and GL_RGB565. GL_DEPTH_COMPONENT16 is the only depth-renderable format. GL_STENCIL_INDEX8 is the only stencil-renderable format.';
  1509. break;
  1510. case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
  1511. message = 'Framebuffer is not complete. Incomplete dimensions: not all attached images have the same width and height.';
  1512. break;
  1513. case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  1514. message = 'Framebuffer is not complete. Missing attachment: no images are attached to the framebuffer.';
  1515. break;
  1516. case gl.FRAMEBUFFER_UNSUPPORTED:
  1517. message = 'Framebuffer is not complete. Unsupported: the combination of internal formats of the attached images violates an implementation-dependent set of restrictions.';
  1518. break;
  1519. }
  1520. throw new DeveloperError(message);
  1521. }
  1522. }
  1523. }
  1524. function applyRenderState(context, renderState, passState) {
  1525. var previousState = context._currentRenderState;
  1526. if (previousState !== renderState) {
  1527. context._currentRenderState = renderState;
  1528. RenderState.partialApply(context._gl, previousState, renderState, passState);
  1529. }
  1530. // else same render state as before so state is already applied.
  1531. }
  1532. var scratchBackBufferArray;
  1533. // this check must use typeof, not defined, because defined doesn't work with undeclared variables.
  1534. if (typeof WebGLRenderingContext !== 'undefined') {
  1535. scratchBackBufferArray = [WebGLRenderingContext.BACK];
  1536. }
  1537. function bindFramebuffer(context, framebuffer) {
  1538. if (framebuffer !== context._currentFramebuffer) {
  1539. context._currentFramebuffer = framebuffer;
  1540. var buffers = scratchBackBufferArray;
  1541. if (defined(framebuffer)) {
  1542. framebuffer._bind();
  1543. validateFramebuffer(context, framebuffer);
  1544. // TODO: Need a way for a command to give what draw buffers are active.
  1545. buffers = framebuffer._getActiveColorAttachments();
  1546. } else {
  1547. var gl = context._gl;
  1548. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  1549. }
  1550. if (context.drawBuffers) {
  1551. context._drawBuffers.drawBuffersWEBGL(buffers);
  1552. }
  1553. }
  1554. }
  1555. var defaultClearCommand = new ClearCommand();
  1556. Context.prototype.clear = function(clearCommand, passState) {
  1557. clearCommand = defaultValue(clearCommand, defaultClearCommand);
  1558. passState = defaultValue(passState, this._defaultPassState);
  1559. var gl = this._gl;
  1560. var bitmask = 0;
  1561. var c = clearCommand.color;
  1562. var d = clearCommand.depth;
  1563. var s = clearCommand.stencil;
  1564. if (defined(c)) {
  1565. if (!Color.equals(this._clearColor, c)) {
  1566. Color.clone(c, this._clearColor);
  1567. gl.clearColor(c.red, c.green, c.blue, c.alpha);
  1568. }
  1569. bitmask |= gl.COLOR_BUFFER_BIT;
  1570. }
  1571. if (defined(d)) {
  1572. if (d !== this._clearDepth) {
  1573. this._clearDepth = d;
  1574. gl.clearDepth(d);
  1575. }
  1576. bitmask |= gl.DEPTH_BUFFER_BIT;
  1577. }
  1578. if (defined(s)) {
  1579. if (s !== this._clearStencil) {
  1580. this._clearStencil = s;
  1581. gl.clearStencil(s);
  1582. }
  1583. bitmask |= gl.STENCIL_BUFFER_BIT;
  1584. }
  1585. var rs = defaultValue(clearCommand.renderState, this._defaultRenderState);
  1586. applyRenderState(this, rs, passState);
  1587. // The command's framebuffer takes presidence over the pass' framebuffer, e.g., for off-screen rendering.
  1588. var framebuffer = defaultValue(clearCommand.framebuffer, passState.framebuffer);
  1589. bindFramebuffer(this, framebuffer);
  1590. gl.clear(bitmask);
  1591. };
  1592. function beginDraw(context, framebuffer, drawCommand, passState, renderState, shaderProgram) {
  1593. var rs = defaultValue(defaultValue(renderState, drawCommand.renderState), context._defaultRenderState);
  1594. //>>includeStart('debug', pragmas.debug);
  1595. if (defined(framebuffer) && rs.depthTest) {
  1596. if (rs.depthTest.enabled && !framebuffer.hasDepthAttachment) {
  1597. throw new DeveloperError('The depth test can not be enabled (drawCommand.renderState.depthTest.enabled) because the framebuffer (drawCommand.framebuffer) does not have a depth or depth-stencil renderbuffer.');
  1598. }
  1599. }
  1600. //>>includeEnd('debug');
  1601. bindFramebuffer(context, framebuffer);
  1602. var sp = defaultValue(shaderProgram, drawCommand.shaderProgram);
  1603. sp._bind();
  1604. context._maxFrameTextureUnitIndex = Math.max(context._maxFrameTextureUnitIndex, sp.maximumTextureUnitIndex);
  1605. applyRenderState(context, rs, passState);
  1606. }
  1607. function continueDraw(context, drawCommand, shaderProgram) {
  1608. var primitiveType = drawCommand.primitiveType;
  1609. var va = drawCommand.vertexArray;
  1610. var offset = drawCommand.offset;
  1611. var count = drawCommand.count;
  1612. //>>includeStart('debug', pragmas.debug);
  1613. if (!PrimitiveType.validate(primitiveType)) {
  1614. throw new DeveloperError('drawCommand.primitiveType is required and must be valid.');
  1615. }
  1616. if (!defined(va)) {
  1617. throw new DeveloperError('drawCommand.vertexArray is required.');
  1618. }
  1619. if (offset < 0) {
  1620. throw new DeveloperError('drawCommand.offset must be omitted or greater than or equal to zero.');
  1621. }
  1622. if (count < 0) {
  1623. throw new DeveloperError('drawCommand.count must be omitted or greater than or equal to zero.');
  1624. }
  1625. //>>includeEnd('debug');
  1626. context._us.model = defaultValue(drawCommand.modelMatrix, Matrix4.IDENTITY);
  1627. var sp = defaultValue(shaderProgram, drawCommand.shaderProgram);
  1628. sp._setUniforms(drawCommand.uniformMap, context._us, context.validateShaderProgram);
  1629. var indexBuffer = va.indexBuffer;
  1630. if (defined(indexBuffer)) {
  1631. offset = offset * indexBuffer.bytesPerIndex; // offset in vertices to offset in bytes
  1632. count = defaultValue(count, indexBuffer.numberOfIndices);
  1633. va._bind();
  1634. context._gl.drawElements(primitiveType, count, indexBuffer.indexDatatype, offset);
  1635. va._unBind();
  1636. } else {
  1637. count = defaultValue(count, va.numberOfVertices);
  1638. va._bind();
  1639. context._gl.drawArrays(primitiveType, offset, count);
  1640. va._unBind();
  1641. }
  1642. }
  1643. Context.prototype.draw = function(drawCommand, passState, renderState, shaderProgram) {
  1644. //>>includeStart('debug', pragmas.debug);
  1645. if (!defined(drawCommand)) {
  1646. throw new DeveloperError('drawCommand is required.');
  1647. }
  1648. if (!defined(drawCommand.shaderProgram)) {
  1649. throw new DeveloperError('drawCommand.shaderProgram is required.');
  1650. }
  1651. //>>includeEnd('debug');
  1652. passState = defaultValue(passState, this._defaultPassState);
  1653. // The command's framebuffer takes presidence over the pass' framebuffer, e.g., for off-screen rendering.
  1654. var framebuffer = defaultValue(drawCommand.framebuffer, passState.framebuffer);
  1655. beginDraw(this, framebuffer, drawCommand, passState, renderState, shaderProgram);
  1656. continueDraw(this, drawCommand, shaderProgram);
  1657. };
  1658. Context.prototype.endFrame = function() {
  1659. var gl = this._gl;
  1660. gl.useProgram(null);
  1661. this._currentFramebuffer = undefined;
  1662. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  1663. var buffers = scratchBackBufferArray;
  1664. if (this.drawBuffers) {
  1665. this._drawBuffers.drawBuffersWEBGL(scratchBackBufferArray);
  1666. }
  1667. var length = this._maxFrameTextureUnitIndex;
  1668. this._maxFrameTextureUnitIndex = 0;
  1669. for (var i = 0; i < length; ++i) {
  1670. gl.activeTexture(gl.TEXTURE0 + i);
  1671. gl.bindTexture(gl.TEXTURE_2D, null);
  1672. gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
  1673. }
  1674. };
  1675. Context.prototype.readPixels = function(readState) {
  1676. var gl = this._gl;
  1677. readState = readState || {};
  1678. var x = Math.max(readState.x || 0, 0);
  1679. var y = Math.max(readState.y || 0, 0);
  1680. var width = readState.width || gl.drawingBufferWidth;
  1681. var height = readState.height || gl.drawingBufferHeight;
  1682. var framebuffer = readState.framebuffer;
  1683. //>>includeStart('debug', pragmas.debug);
  1684. if (width <= 0) {
  1685. throw new DeveloperError('readState.width must be greater than zero.');
  1686. }
  1687. if (height <= 0) {
  1688. throw new DeveloperError('readState.height must be greater than zero.');
  1689. }
  1690. //>>includeEnd('debug');
  1691. var pixels = new Uint8Array(4 * width * height);
  1692. bindFramebuffer(this, framebuffer);
  1693. gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  1694. return pixels;
  1695. };
  1696. //////////////////////////////////////////////////////////////////////////////////////////
  1697. function computeNumberOfVertices(attribute) {
  1698. return attribute.values.length / attribute.componentsPerAttribute;
  1699. }
  1700. function computeAttributeSizeInBytes(attribute) {
  1701. return ComponentDatatype.getSizeInBytes(attribute.componentDatatype) * attribute.componentsPerAttribute;
  1702. }
  1703. function interleaveAttributes(attributes) {
  1704. var j;
  1705. var name;
  1706. var attribute;
  1707. // Extract attribute names.
  1708. var names = [];
  1709. for (name in attributes) {
  1710. // Attribute needs to have per-vertex values; not a constant value for all vertices.
  1711. if (attributes.hasOwnProperty(name) &&
  1712. defined(attributes[name]) &&
  1713. defined(attributes[name].values)) {
  1714. names.push(name);
  1715. if (attributes[name].componentDatatype === ComponentDatatype.DOUBLE) {
  1716. attributes[name].componentDatatype = ComponentDatatype.FLOAT;
  1717. attributes[name].values = ComponentDatatype.createTypedArray(ComponentDatatype.FLOAT, attributes[name].values);
  1718. }
  1719. }
  1720. }
  1721. // Validation. Compute number of vertices.
  1722. var numberOfVertices;
  1723. var namesLength = names.length;
  1724. if (namesLength > 0) {
  1725. numberOfVertices = computeNumberOfVertices(attributes[names[0]]);
  1726. for (j = 1; j < namesLength; ++j) {
  1727. var currentNumberOfVertices = computeNumberOfVertices(attributes[names[j]]);
  1728. if (currentNumberOfVertices !== numberOfVertices) {
  1729. throw new RuntimeError(
  1730. 'Each attribute list must have the same number of vertices. ' +
  1731. 'Attribute ' + names[j] + ' has a different number of vertices ' +
  1732. '(' + currentNumberOfVertices.toString() + ')' +
  1733. ' than attribute ' + names[0] +
  1734. ' (' + numberOfVertices.toString() + ').');
  1735. }
  1736. }
  1737. }
  1738. // Sort attributes by the size of their components. From left to right, a vertex stores floats, shorts, and then bytes.
  1739. names.sort(function(left, right) {
  1740. return ComponentDatatype.getSizeInBytes(attributes[right].componentDatatype) - ComponentDatatype.getSizeInBytes(attributes[left].componentDatatype);
  1741. });
  1742. // Compute sizes and strides.
  1743. var vertexSizeInBytes = 0;
  1744. var offsetsInBytes = {};
  1745. for (j = 0; j < namesLength; ++j) {
  1746. name = names[j];
  1747. attribute = attributes[name];
  1748. offsetsInBytes[name] = vertexSizeInBytes;
  1749. vertexSizeInBytes += computeAttributeSizeInBytes(attribute);
  1750. }
  1751. if (vertexSizeInBytes > 0) {
  1752. // Pad each vertex to be a multiple of the largest component datatype so each
  1753. // attribute can be addressed using typed arrays.
  1754. var maxComponentSizeInBytes = ComponentDatatype.getSizeInBytes(attributes[names[0]].componentDatatype); // Sorted large to small
  1755. var remainder = vertexSizeInBytes % maxComponentSizeInBytes;
  1756. if (remainder !== 0) {
  1757. vertexSizeInBytes += (maxComponentSizeInBytes - remainder);
  1758. }
  1759. // Total vertex buffer size in bytes, including per-vertex padding.
  1760. var vertexBufferSizeInBytes = numberOfVertices * vertexSizeInBytes;
  1761. // Create array for interleaved vertices. Each attribute has a different view (pointer) into the array.
  1762. var buffer = new ArrayBuffer(vertexBufferSizeInBytes);
  1763. var views = {};
  1764. for (j = 0; j < namesLength; ++j) {
  1765. name = names[j];
  1766. var sizeInBytes = ComponentDatatype.getSizeInBytes(attributes[name].componentDatatype);
  1767. views[name] = {
  1768. pointer : ComponentDatatype.createTypedArray(attributes[name].componentDatatype, buffer),
  1769. index : offsetsInBytes[name] / sizeInBytes, // Offset in ComponentType
  1770. strideInComponentType : vertexSizeInBytes / sizeInBytes
  1771. };
  1772. }
  1773. // Copy attributes into one interleaved array.
  1774. // PERFORMANCE_IDEA: Can we optimize these loops?
  1775. for (j = 0; j < numberOfVertices; ++j) {
  1776. for ( var n = 0; n < namesLength; ++n) {
  1777. name = names[n];
  1778. attribute = attributes[name];
  1779. var values = attribute.values;
  1780. var view = views[name];
  1781. var pointer = view.pointer;
  1782. var numberOfComponents = attribute.componentsPerAttribute;
  1783. for ( var k = 0; k < numberOfComponents; ++k) {
  1784. pointer[view.index + k] = values[(j * numberOfComponents) + k];
  1785. }
  1786. view.index += view.strideInComponentType;
  1787. }
  1788. }
  1789. return {
  1790. buffer : buffer,
  1791. offsetsInBytes : offsetsInBytes,
  1792. vertexSizeInBytes : vertexSizeInBytes
  1793. };
  1794. }
  1795. // No attributes to interleave.
  1796. return undefined;
  1797. }
  1798. /**
  1799. * Creates a vertex array from a geometry. A geometry contains vertex attributes and optional index data
  1800. * in system memory, whereas a vertex array contains vertex buffers and an optional index buffer in WebGL
  1801. * memory for use with rendering.
  1802. * <br /><br />
  1803. * The <code>geometry</code> argument should use the standard layout like the geometry returned by {@link BoxGeometry}.
  1804. * <br /><br />
  1805. * <code>options</code> can have four properties:
  1806. * <ul>
  1807. * <li><code>geometry</code>: The source geometry containing data used to create the vertex array.</li>
  1808. * <li><code>attributeLocations</code>: An object that maps geometry attribute names to vertex shader attribute locations.</li>
  1809. * <li><code>bufferUsage</code>: The expected usage pattern of the vertex array's buffers. On some WebGL implementations, this can significantly affect performance. See {@link BufferUsage}. Default: <code>BufferUsage.DYNAMIC_DRAW</code>.</li>
  1810. * <li><code>interleave</code>: Determines if all attributes are interleaved in a single vertex buffer or if each attribute is stored in a separate vertex buffer. Default: <code>false</code>.</li>
  1811. * </ul>
  1812. * <br />
  1813. * If <code>options</code> is not specified or the <code>geometry</code> contains no data, the returned vertex array is empty.
  1814. *
  1815. * @param {Object} [options] An object defining the geometry, attribute indices, buffer usage, and vertex layout used to create the vertex array.
  1816. *
  1817. * @exception {RuntimeError} Each attribute list must have the same number of vertices.
  1818. * @exception {DeveloperError} The geometry must have zero or one index lists.
  1819. * @exception {DeveloperError} Index n is used by more than one attribute.
  1820. *
  1821. * @see Context#createVertexArray
  1822. * @see Context#createVertexBuffer
  1823. * @see Context#createIndexBuffer
  1824. * @see GeometryPipeline.createAttributeLocations
  1825. * @see ShaderProgram
  1826. *
  1827. * @example
  1828. * // Example 1. Creates a vertex array for rendering a box. The default dynamic draw
  1829. * // usage is used for the created vertex and index buffer. The attributes are not
  1830. * // interleaved by default.
  1831. * var geometry = new BoxGeometry();
  1832. * var va = context.createVertexArrayFromGeometry({
  1833. * geometry : geometry,
  1834. * attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
  1835. * });
  1836. *
  1837. * @example
  1838. * // Example 2. Creates a vertex array with interleaved attributes in a
  1839. * // single vertex buffer. The vertex and index buffer have static draw usage.
  1840. * var va = context.createVertexArrayFromGeometry({
  1841. * geometry : geometry,
  1842. * attributeLocations : GeometryPipeline.createAttributeLocations(geometry),
  1843. * bufferUsage : BufferUsage.STATIC_DRAW,
  1844. * interleave : true
  1845. * });
  1846. *
  1847. * @example
  1848. * // Example 3. When the caller destroys the vertex array, it also destroys the
  1849. * // attached vertex buffer(s) and index buffer.
  1850. * va = va.destroy();
  1851. */
  1852. Context.prototype.createVertexArrayFromGeometry = function(options) {
  1853. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  1854. var geometry = defaultValue(options.geometry, defaultValue.EMPTY_OBJECT);
  1855. var bufferUsage = defaultValue(options.bufferUsage, BufferUsage.DYNAMIC_DRAW);
  1856. var attributeLocations = defaultValue(options.attributeLocations, defaultValue.EMPTY_OBJECT);
  1857. var interleave = defaultValue(options.interleave, false);
  1858. var createdVAAttributes = options.vertexArrayAttributes;
  1859. var name;
  1860. var attribute;
  1861. var vertexBuffer;
  1862. var vaAttributes = (defined(createdVAAttributes)) ? createdVAAttributes : [];
  1863. var attributes = geometry.attributes;
  1864. if (interleave) {
  1865. // Use a single vertex buffer with interleaved vertices.
  1866. var interleavedAttributes = interleaveAttributes(attributes);
  1867. if (defined(interleavedAttributes)) {
  1868. vertexBuffer = this.createVertexBuffer(interleavedAttributes.buffer, bufferUsage);
  1869. var offsetsInBytes = interleavedAttributes.offsetsInBytes;
  1870. var strideInBytes = interleavedAttributes.vertexSizeInBytes;
  1871. for (name in attributes) {
  1872. if (attributes.hasOwnProperty(name) && defined(attributes[name])) {
  1873. attribute = attributes[name];
  1874. if (defined(attribute.values)) {
  1875. // Common case: per-vertex attributes
  1876. vaAttributes.push({
  1877. index : attributeLocations[name],
  1878. vertexBuffer : vertexBuffer,
  1879. componentDatatype : attribute.componentDatatype,
  1880. componentsPerAttribute : attribute.componentsPerAttribute,
  1881. normalize : attribute.normalize,
  1882. offsetInBytes : offsetsInBytes[name],
  1883. strideInBytes : strideInBytes
  1884. });
  1885. } else {
  1886. // Constant attribute for all vertices
  1887. vaAttributes.push({
  1888. index : attributeLocations[name],
  1889. value : attribute.value,
  1890. componentDatatype : attribute.componentDatatype,
  1891. normalize : attribute.normalize
  1892. });
  1893. }
  1894. }
  1895. }
  1896. }
  1897. } else {
  1898. // One vertex buffer per attribute.
  1899. for (name in attributes) {
  1900. if (attributes.hasOwnProperty(name) && defined(attributes[name])) {
  1901. attribute = attributes[name];
  1902. var componentDatatype = attribute.componentDatatype;
  1903. if (componentDatatype === ComponentDatatype.DOUBLE) {
  1904. componentDatatype = ComponentDatatype.FLOAT;
  1905. }
  1906. vertexBuffer = undefined;
  1907. if (defined(attribute.values)) {
  1908. vertexBuffer = this.createVertexBuffer(ComponentDatatype.createTypedArray(componentDatatype, attribute.values), bufferUsage);
  1909. }
  1910. vaAttributes.push({
  1911. index : attributeLocations[name],
  1912. vertexBuffer : vertexBuffer,
  1913. value : attribute.value,
  1914. componentDatatype : componentDatatype,
  1915. componentsPerAttribute : attribute.componentsPerAttribute,
  1916. normalize : attribute.normalize
  1917. });
  1918. }
  1919. }
  1920. }
  1921. var indexBuffer;
  1922. var indices = geometry.indices;
  1923. if (defined(indices)) {
  1924. if ((Geometry.computeNumberOfVertices(geometry) > CesiumMath.SIXTY_FOUR_KILOBYTES) && this.elementIndexUint) {
  1925. indexBuffer = this.createIndexBuffer(new Uint32Array(indices), bufferUsage, IndexDatatype.UNSIGNED_INT);
  1926. } else{
  1927. indexBuffer = this.createIndexBuffer(new Uint16Array(indices), bufferUsage, IndexDatatype.UNSIGNED_SHORT);
  1928. }
  1929. }
  1930. return this.createVertexArray(vaAttributes, indexBuffer);
  1931. };
  1932. var viewportQuadAttributeLocations = {
  1933. position : 0,
  1934. textureCoordinates : 1
  1935. };
  1936. Context.prototype.createViewportQuadCommand = function(fragmentShaderSource, overrides) {
  1937. // Per-context cache for viewport quads
  1938. var vertexArray = this.cache.viewportQuad_vertexArray;
  1939. if (!defined(vertexArray)) {
  1940. var geometry = new Geometry({
  1941. attributes : {
  1942. position : new GeometryAttribute({
  1943. componentDatatype : ComponentDatatype.FLOAT,
  1944. componentsPerAttribute : 2,
  1945. values : [
  1946. -1.0, -1.0,
  1947. 1.0, -1.0,
  1948. 1.0, 1.0,
  1949. -1.0, 1.0
  1950. ]
  1951. }),
  1952. textureCoordinates : new GeometryAttribute({
  1953. componentDatatype : ComponentDatatype.FLOAT,
  1954. componentsPerAttribute : 2,
  1955. values : [
  1956. 0.0, 0.0,
  1957. 1.0, 0.0,
  1958. 1.0, 1.0,
  1959. 0.0, 1.0
  1960. ]
  1961. })
  1962. },
  1963. // Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
  1964. indices : new Uint16Array([0, 1, 2, 0, 2, 3]),
  1965. primitiveType : PrimitiveType.TRIANGLES
  1966. });
  1967. vertexArray = this.createVertexArrayFromGeometry({
  1968. geometry : geometry,
  1969. attributeLocations : {
  1970. position : 0,
  1971. textureCoordinates : 1
  1972. },
  1973. bufferUsage : BufferUsage.STATIC_DRAW,
  1974. interleave : true
  1975. });
  1976. this.cache.viewportQuad_vertexArray = vertexArray;
  1977. }
  1978. overrides = defaultValue(overrides, defaultValue.EMPTY_OBJECT);
  1979. return new DrawCommand({
  1980. vertexArray : vertexArray,
  1981. primitiveType : PrimitiveType.TRIANGLES,
  1982. renderState : overrides.renderState,
  1983. shaderProgram : this.createShaderProgram(ViewportQuadVS, fragmentShaderSource, viewportQuadAttributeLocations),
  1984. uniformMap : overrides.uniformMap,
  1985. owner : overrides.owner,
  1986. framebuffer : overrides.framebuffer
  1987. });
  1988. };
  1989. Context.prototype.createPickFramebuffer = function() {
  1990. return new PickFramebuffer(this);
  1991. };
  1992. /**
  1993. * Gets the object associated with a pick color.
  1994. *
  1995. * @param {Color} pickColor The pick color.
  1996. * @returns {Object} The object associated with the pick color, or undefined if no object is associated with that color.
  1997. *
  1998. * @see Context#createPickId
  1999. *
  2000. * @example
  2001. * var object = context.getObjectByPickColor(pickColor);
  2002. */
  2003. Context.prototype.getObjectByPickColor = function(pickColor) {
  2004. //>>includeStart('debug', pragmas.debug);
  2005. if (!defined(pickColor)) {
  2006. throw new DeveloperError('pickColor is required.');
  2007. }
  2008. //>>includeEnd('debug');
  2009. return this._pickObjects[pickColor.toRgba()];
  2010. };
  2011. function PickId(pickObjects, key, color) {
  2012. this._pickObjects = pickObjects;
  2013. this.key = key;
  2014. this.color = color;
  2015. }
  2016. defineProperties(PickId.prototype, {
  2017. object : {
  2018. get : function() {
  2019. return this._pickObjects[this.key];
  2020. },
  2021. set : function(value) {
  2022. this._pickObjects[this.key] = value;
  2023. }
  2024. }
  2025. });
  2026. PickId.prototype.destroy = function() {
  2027. delete this._pickObjects[this.key];
  2028. return undefined;
  2029. };
  2030. /**
  2031. * Creates a unique ID associated with the input object for use with color-buffer picking.
  2032. * The ID has an RGBA color value unique to this context. You must call destroy()
  2033. * on the pick ID when destroying the input object.
  2034. *
  2035. * @param {Object} object The object to associate with the pick ID.
  2036. * @returns {Object} A PickId object with a <code>color</code> property.
  2037. *
  2038. * @exception {RuntimeError} Out of unique Pick IDs.
  2039. *
  2040. * @see Context#getObjectByPickColor
  2041. *
  2042. * @example
  2043. * this._pickId = context.createPickId({
  2044. * primitive : this,
  2045. * id : this.id
  2046. * });
  2047. */
  2048. Context.prototype.createPickId = function(object) {
  2049. //>>includeStart('debug', pragmas.debug);
  2050. if (!defined(object)) {
  2051. throw new DeveloperError('object is required.');
  2052. }
  2053. //>>includeEnd('debug');
  2054. // the increment and assignment have to be separate statements to
  2055. // actually detect overflow in the Uint32 value
  2056. ++this._nextPickColor[0];
  2057. var key = this._nextPickColor[0];
  2058. if (key === 0) {
  2059. // In case of overflow
  2060. throw new RuntimeError('Out of unique Pick IDs.');
  2061. }
  2062. this._pickObjects[key] = object;
  2063. return new PickId(this._pickObjects, key, Color.fromRgba(key));
  2064. };
  2065. Context.prototype.isDestroyed = function() {
  2066. return false;
  2067. };
  2068. Context.prototype.destroy = function() {
  2069. // Destroy all objects in the cache that have a destroy method.
  2070. var cache = this.cache;
  2071. for (var property in cache) {
  2072. if (cache.hasOwnProperty(property)) {
  2073. var propertyValue = cache[property];
  2074. if (defined(propertyValue.destroy)) {
  2075. propertyValue.destroy();
  2076. }
  2077. }
  2078. }
  2079. this._shaderCache = this._shaderCache.destroy();
  2080. this._defaultTexture = this._defaultTexture && this._defaultTexture.destroy();
  2081. this._defaultCubeMap = this._defaultCubeMap && this._defaultCubeMap.destroy();
  2082. return destroyObject(this);
  2083. };
  2084. return Context;
  2085. });