WebGLRenderer3.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. *
  4. * parameters = {
  5. * canvas: canvas,
  6. * contextAttributes: {
  7. * alpha: true,
  8. * depth: true,
  9. * stencil: false,
  10. * antialias: true,
  11. * premultipliedAlpha: true,
  12. * preserveDrawingBuffer: false
  13. * }
  14. * }
  15. *
  16. */
  17. THREE.WebGLRenderer3 = function ( parameters ) {
  18. console.log( 'THREE.WebGLRenderer3', THREE.REVISION );
  19. parameters = parameters || {};
  20. var canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' );
  21. var devicePixelRatio = parameters.devicePixelRatio !== undefined
  22. ? parameters.devicePixelRatio
  23. : window.devicePixelRatio !== undefined
  24. ? window.devicePixelRatio
  25. : 1;
  26. var gl;
  27. try {
  28. var attributes = parameters.contextAttributes || {}
  29. gl = canvas.getContext( 'webgl', attributes ) || canvas.getContext( 'experimental-webgl', attributes );
  30. } catch ( exception ) {
  31. console.error( exception );
  32. }
  33. var precision = 'highp';
  34. var extensions = {};
  35. if ( gl !== null ) {
  36. extensions.element_index_uint = gl.getExtension( 'OES_element_index_uint' );
  37. extensions.texture_float = gl.getExtension( 'OES_texture_float' );
  38. extensions.standard_derivatives = gl.getExtension( 'OES_standard_derivatives' );
  39. extensions.texture_filter_anisotropic = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
  40. extensions.compressed_texture_s3tc = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
  41. gl.clearColor( 0, 0, 0, 1 );
  42. gl.clearDepth( 1 );
  43. gl.clearStencil( 0 );
  44. gl.enable( gl.DEPTH_TEST );
  45. gl.depthFunc( gl.LEQUAL );
  46. gl.enable( gl.CULL_FACE );
  47. gl.frontFace( gl.CCW );
  48. gl.cullFace( gl.BACK );
  49. gl.enable( gl.BLEND );
  50. gl.blendEquation( gl.FUNC_ADD );
  51. gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
  52. gl.clearColor( 0, 0, 0, 1 );
  53. }
  54. var clearColor = new THREE.Color( 0x000000 );
  55. var clearAlpha = 1;
  56. //
  57. var frustum = new THREE.Frustum();
  58. var modelViewMatrix = new THREE.Matrix4();
  59. var modelViewProjectionMatrix = new THREE.Matrix4();
  60. // buffers
  61. var buffers = {};
  62. var getBuffer = function ( geometry ) {
  63. if ( buffers[ geometry.id ] !== undefined ) {
  64. return buffers[ geometry.id ];
  65. }
  66. var vertices = geometry.vertices;
  67. var faces = geometry.faces;
  68. //
  69. var positions = [];
  70. var addPosition = function ( position ) {
  71. positions.push( position.x, position.y, position.z );
  72. }
  73. var colors = [];
  74. var addColor = function ( color ) {
  75. colors.push( color.r, color.g, color.b );
  76. }
  77. for ( var i = 0, l = faces.length; i < l; i ++ ) {
  78. var face = faces[ i ];
  79. addPosition( vertices[ face.a ] );
  80. addPosition( vertices[ face.b ] );
  81. addPosition( vertices[ face.c ] );
  82. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  83. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  84. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  85. if ( face instanceof THREE.Face4 ) {
  86. addPosition( vertices[ face.a ] );
  87. addPosition( vertices[ face.c ] );
  88. addPosition( vertices[ face.d ] );
  89. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  90. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  91. addColor( new THREE.Color( 0xffffff * Math.random() ) );
  92. }
  93. }
  94. var buffer = {
  95. positions: gl.createBuffer(),
  96. colors: gl.createBuffer(),
  97. count: positions.length / 3
  98. };
  99. gl.bindBuffer( gl.ARRAY_BUFFER, buffer.positions );
  100. gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( positions ), gl.STATIC_DRAW );
  101. gl.bindBuffer( gl.ARRAY_BUFFER, buffer.colors );
  102. gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( colors ), gl.STATIC_DRAW );
  103. buffers[ geometry.id ] = buffer;
  104. return buffer;
  105. };
  106. // programs
  107. var programs = {};
  108. var getProgram = function ( material ) {
  109. if ( programs[ material.id ] !== undefined ) {
  110. return programs[ material.id ];
  111. }
  112. var program = gl.createProgram();
  113. var vertexShader = [
  114. 'precision ' + precision + ' float;',
  115. 'attribute vec3 position;',
  116. 'attribute vec3 color;',
  117. 'uniform mat4 modelViewMatrix;',
  118. 'uniform mat4 projectionMatrix;',
  119. 'varying vec3 vColor;',
  120. 'void main() {',
  121. ' vColor = color;',
  122. ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
  123. '}'
  124. ].join( '\n' );
  125. var fragmentShader = [
  126. 'precision ' + precision + ' float;',
  127. 'varying vec3 vColor;',
  128. 'void main() {',
  129. ' gl_FragColor = vec4(vColor,1);',
  130. '}'
  131. ].join( '\n' );
  132. gl.attachShader( program, createShader( gl.VERTEX_SHADER, vertexShader ) );
  133. gl.attachShader( program, createShader( gl.FRAGMENT_SHADER, fragmentShader ) );
  134. gl.linkProgram( program );
  135. if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === true ) {
  136. programs[ material.id ] = program;
  137. } else {
  138. programs[ material.id ] = null;
  139. console.error( 'VALIDATE_STATUS: ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) );
  140. console.error( 'GL_ERROR: ' + gl.getError() );
  141. }
  142. return program;
  143. };
  144. var createShader = function ( type, string ) {
  145. var shader = gl.createShader( type );
  146. gl.shaderSource( shader, string );
  147. gl.compileShader( shader );
  148. if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === true ) {
  149. // console.log( string );
  150. } else {
  151. console.error( gl.getShaderInfoLog( shader ), string );
  152. return null;
  153. }
  154. return shader;
  155. };
  156. this.domElement = canvas;
  157. this.extensions = extensions;
  158. this.setClearColor = function ( color, alpha ) {
  159. clearColor.set( color );
  160. clearAlpha = alpha !== undefined ? alpha : 1;
  161. gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
  162. };
  163. this.setSize = function ( width, height, updateStyle ) {
  164. canvas.width = width;
  165. canvas.height = height;
  166. if ( devicePixelRatio !== 1 && updateStyle !== false ) {
  167. canvas.style.width = width + 'px';
  168. canvas.style.height = height + 'px';
  169. }
  170. gl.viewport( 0, 0, canvas.width, canvas.height );
  171. };
  172. this.clear = function ( color, depth, stencil ) {
  173. var bits = 0;
  174. if ( color === undefined || color ) bits |= gl.COLOR_BUFFER_BIT;
  175. if ( depth === undefined || depth ) bits |= gl.DEPTH_BUFFER_BIT;
  176. if ( stencil === undefined || stencil ) bits |= gl.STENCIL_BUFFER_BIT;
  177. gl.clear( bits );
  178. };
  179. this.render = function ( scene, camera ) {
  180. if ( this.autoClear === true ) this.clear();
  181. scene.updateMatrixWorld();
  182. if ( camera.parent === undefined ) camera.updateMatrixWorld();
  183. camera.matrixWorldInverse.getInverse( camera.matrixWorld );
  184. modelViewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
  185. frustum.setFromMatrix( modelViewProjectionMatrix );
  186. var currentBuffer, currentProgram;
  187. var locations = {};
  188. for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
  189. var object = scene.children[ i ];
  190. if ( object.visible === false ) continue;
  191. if ( object instanceof THREE.Mesh && frustum.intersectsObject( object ) === true ) {
  192. var program = getProgram( object.material );
  193. if ( program !== currentProgram ) {
  194. gl.useProgram( program );
  195. locations.modelViewMatrix = gl.getUniformLocation( program, 'modelViewMatrix' );
  196. locations.projectionMatrix = gl.getUniformLocation( program, 'projectionMatrix' );
  197. locations.position = gl.getAttribLocation( program, 'position' );
  198. locations.color = gl.getAttribLocation( program, 'color' );
  199. gl.uniformMatrix4fv( locations.projectionMatrix, false, camera.projectionMatrix.elements );
  200. currentProgram = program;
  201. }
  202. var buffer = getBuffer( object.geometry );
  203. if ( buffer !== currentBuffer ) {
  204. gl.bindBuffer( gl.ARRAY_BUFFER, buffer.positions );
  205. gl.enableVertexAttribArray( locations.position );
  206. gl.vertexAttribPointer( locations.position, 3, gl.FLOAT, false, 0, 0 );
  207. gl.bindBuffer( gl.ARRAY_BUFFER, buffer.colors );
  208. gl.enableVertexAttribArray( locations.color );
  209. gl.vertexAttribPointer( locations.color, 3, gl.FLOAT, false, 0, 0 );
  210. currentBuffer = buffer;
  211. }
  212. modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
  213. gl.uniformMatrix4fv( locations.modelViewMatrix, false, modelViewMatrix.elements );
  214. gl.drawArrays( gl.TRIANGLES, 0, buffer.count );
  215. }
  216. }
  217. };
  218. };