WebGLState.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
  5. var _this = this;
  6. var newAttributes = new Uint8Array( 16 );
  7. var enabledAttributes = new Uint8Array( 16 );
  8. var capabilities = {};
  9. var compressedTextureFormats = null;
  10. var currentBlending = null;
  11. var currentBlendEquation = null;
  12. var currentBlendSrc = null;
  13. var currentBlendDst = null;
  14. var currentBlendEquationAlpha = null;
  15. var currentBlendSrcAlpha = null;
  16. var currentBlendDstAlpha = null;
  17. var currentDepthFunc = null;
  18. var currentDepthWrite = null;
  19. var currentColorWrite = null;
  20. var currentFlipSided = null;
  21. var currentLineWidth = null;
  22. var currentPolygonOffsetFactor = null;
  23. var currentPolygonOffsetUnits = null;
  24. var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
  25. var currentTextureSlot = undefined;
  26. var currentBoundTextures = {};
  27. this.init = function () {
  28. gl.clearColor( 0, 0, 0, 1 );
  29. gl.clearDepth( 1 );
  30. gl.clearStencil( 0 );
  31. this.enable( gl.DEPTH_TEST );
  32. gl.depthFunc( gl.LEQUAL );
  33. gl.frontFace( gl.CCW );
  34. gl.cullFace( gl.BACK );
  35. this.enable( gl.CULL_FACE );
  36. this.enable( gl.BLEND );
  37. gl.blendEquation( gl.FUNC_ADD );
  38. gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
  39. };
  40. this.initAttributes = function () {
  41. for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
  42. newAttributes[ i ] = 0;
  43. }
  44. };
  45. this.enableAttribute = function ( attribute ) {
  46. newAttributes[ attribute ] = 1;
  47. if ( enabledAttributes[ attribute ] === 0 ) {
  48. gl.enableVertexAttribArray( attribute );
  49. enabledAttributes[ attribute ] = 1;
  50. }
  51. };
  52. this.disableUnusedAttributes = function () {
  53. for ( var i = 0, l = enabledAttributes.length; i < l; i ++ ) {
  54. if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
  55. gl.disableVertexAttribArray( i );
  56. enabledAttributes[ i ] = 0;
  57. }
  58. }
  59. };
  60. this.enable = function ( id ) {
  61. if ( capabilities[ id ] !== true ) {
  62. gl.enable( id );
  63. capabilities[ id ] = true;
  64. }
  65. };
  66. this.disable = function ( id ) {
  67. if ( capabilities[ id ] !== false ) {
  68. gl.disable( id );
  69. capabilities[ id ] = false;
  70. }
  71. };
  72. this.getCompressedTextureFormats = function () {
  73. if ( compressedTextureFormats === null ) {
  74. compressedTextureFormats = [];
  75. if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
  76. extensions.get( 'WEBGL_compressed_texture_s3tc' ) ) {
  77. var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
  78. for ( var i = 0; i < formats.length; i ++ ) {
  79. compressedTextureFormats.push( formats[ i ] );
  80. }
  81. }
  82. }
  83. return compressedTextureFormats;
  84. };
  85. this.setBlending = function ( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha ) {
  86. if ( blending !== currentBlending ) {
  87. if ( blending === THREE.NoBlending ) {
  88. this.disable( gl.BLEND );
  89. } else if ( blending === THREE.AdditiveBlending ) {
  90. this.enable( gl.BLEND );
  91. gl.blendEquation( gl.FUNC_ADD );
  92. gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
  93. } else if ( blending === THREE.SubtractiveBlending ) {
  94. // TODO: Find blendFuncSeparate() combination
  95. this.enable( gl.BLEND );
  96. gl.blendEquation( gl.FUNC_ADD );
  97. gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
  98. } else if ( blending === THREE.MultiplyBlending ) {
  99. // TODO: Find blendFuncSeparate() combination
  100. this.enable( gl.BLEND );
  101. gl.blendEquation( gl.FUNC_ADD );
  102. gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
  103. } else if ( blending === THREE.CustomBlending ) {
  104. this.enable( gl.BLEND );
  105. } else {
  106. this.enable( gl.BLEND );
  107. gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
  108. gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
  109. }
  110. currentBlending = blending;
  111. }
  112. if ( blending === THREE.CustomBlending ) {
  113. blendEquationAlpha = blendEquationAlpha || blendEquation;
  114. blendSrcAlpha = blendSrcAlpha || blendSrc;
  115. blendDstAlpha = blendDstAlpha || blendDst;
  116. if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
  117. gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) );
  118. currentBlendEquation = blendEquation;
  119. currentBlendEquationAlpha = blendEquationAlpha;
  120. }
  121. if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
  122. gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) );
  123. currentBlendSrc = blendSrc;
  124. currentBlendDst = blendDst;
  125. currentBlendSrcAlpha = blendSrcAlpha;
  126. currentBlendDstAlpha = blendDstAlpha;
  127. }
  128. } else {
  129. currentBlendEquation = null;
  130. currentBlendSrc = null;
  131. currentBlendDst = null;
  132. currentBlendEquationAlpha = null;
  133. currentBlendSrcAlpha = null;
  134. currentBlendDstAlpha = null;
  135. }
  136. };
  137. this.setDepthFunc = function ( depthFunc ) {
  138. if ( currentDepthFunc !== depthFunc ) {
  139. if ( depthFunc ) {
  140. switch ( depthFunc ) {
  141. case THREE.NeverDepth:
  142. gl.depthFunc( gl.NEVER );
  143. break;
  144. case THREE.AlwaysDepth:
  145. gl.depthFunc( gl.ALWAYS );
  146. break;
  147. case THREE.LessDepth:
  148. gl.depthFunc( gl.LESS );
  149. break;
  150. case THREE.LessEqualDepth:
  151. gl.depthFunc( gl.LEQUAL );
  152. break;
  153. case THREE.EqualDepth:
  154. gl.depthFunc( gl.EQUAL );
  155. break;
  156. case THREE.GreaterEqualDepth:
  157. gl.depthFunc( gl.GEQUAL );
  158. break;
  159. case THREE.GreaterDepth:
  160. gl.depthFunc( gl.GREATER );
  161. break;
  162. case THREE.NotEqualDepth:
  163. gl.depthFunc( gl.NOTEQUAL );
  164. break;
  165. default:
  166. gl.depthFunc( gl.LEQUAL );
  167. }
  168. } else {
  169. gl.depthFunc( gl.LEQUAL );
  170. }
  171. currentDepthFunc = depthFunc;
  172. }
  173. };
  174. this.setDepthTest = function ( depthTest ) {
  175. if ( depthTest ) {
  176. this.enable( gl.DEPTH_TEST );
  177. } else {
  178. this.disable( gl.DEPTH_TEST );
  179. }
  180. };
  181. this.setDepthWrite = function ( depthWrite ) {
  182. if ( currentDepthWrite !== depthWrite ) {
  183. gl.depthMask( depthWrite );
  184. currentDepthWrite = depthWrite;
  185. }
  186. };
  187. this.setColorWrite = function ( colorWrite ) {
  188. if ( currentColorWrite !== colorWrite ) {
  189. gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite );
  190. currentColorWrite = colorWrite;
  191. }
  192. };
  193. this.setFlipSided = function ( flipSided ) {
  194. if ( currentFlipSided !== flipSided ) {
  195. if ( flipSided ) {
  196. gl.frontFace( gl.CW );
  197. } else {
  198. gl.frontFace( gl.CCW );
  199. }
  200. currentFlipSided = flipSided;
  201. }
  202. };
  203. this.setLineWidth = function ( width ) {
  204. if ( width !== currentLineWidth ) {
  205. gl.lineWidth( width );
  206. currentLineWidth = width;
  207. }
  208. };
  209. this.setPolygonOffset = function ( polygonOffset, factor, units ) {
  210. if ( polygonOffset ) {
  211. this.enable( gl.POLYGON_OFFSET_FILL );
  212. } else {
  213. this.disable( gl.POLYGON_OFFSET_FILL );
  214. }
  215. if ( polygonOffset && ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) ) {
  216. gl.polygonOffset( factor, units );
  217. currentPolygonOffsetFactor = factor;
  218. currentPolygonOffsetUnits = units;
  219. }
  220. };
  221. this.setScissorTest = function ( scissorTest ) {
  222. if ( scissorTest ) {
  223. this.enable( gl.SCISSOR_TEST );
  224. } else {
  225. this.disable( gl.SCISSOR_TEST );
  226. }
  227. };
  228. // texture
  229. this.activeTexture = function ( webglSlot ) {
  230. if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
  231. if ( currentTextureSlot !== webglSlot ) {
  232. gl.activeTexture( webglSlot );
  233. currentTextureSlot = webglSlot;
  234. }
  235. }
  236. this.bindTexture = function ( webglType, webglTexture ) {
  237. if ( currentTextureSlot === undefined ) {
  238. _this.activeTexture();
  239. }
  240. var boundTexture = currentBoundTextures[ currentTextureSlot ];
  241. if ( boundTexture === undefined ) {
  242. boundTexture = { type: undefined, texture: undefined };
  243. currentBoundTextures[ currentTextureSlot ] = boundTexture;
  244. }
  245. if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
  246. gl.bindTexture( webglType, webglTexture );
  247. boundTexture.type = webglType;
  248. boundTexture.texture = webglTexture;
  249. }
  250. };
  251. this.compressedTexImage2D = function () {
  252. try {
  253. gl.compressedTexImage2D.apply( gl, arguments );
  254. } catch ( error ) {
  255. console.error( error );
  256. }
  257. };
  258. this.texImage2D = function () {
  259. try {
  260. gl.texImage2D.apply( gl, arguments );
  261. } catch ( error ) {
  262. console.error( error );
  263. }
  264. };
  265. //
  266. this.reset = function () {
  267. for ( var i = 0; i < enabledAttributes.length; i ++ ) {
  268. if ( enabledAttributes[ i ] === 1 ) {
  269. gl.disableVertexAttribArray( i );
  270. enabledAttributes[ i ] = 0;
  271. }
  272. }
  273. capabilities = {};
  274. compressedTextureFormats = null;
  275. currentBlending = null;
  276. currentDepthWrite = null;
  277. currentColorWrite = null;
  278. currentFlipSided = null;
  279. };
  280. };