WebGLRenderer.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /**
  2. * @author supereggbert / http://www.paulbrunt.co.uk/
  3. * @author mrdoob / http://mrdoob.com/
  4. */
  5. THREE.WebGLRenderer = function () {
  6. var _canvas = document.createElement( 'canvas' ), _gl, _program,
  7. _modelViewMatrix = new THREE.Matrix4(), _normalMatrix,
  8. COLORFILL = 0, COLORSTROKE = 1, BITMAP = 2, PHONG = 3; // material constants used in shader
  9. this.domElement = _canvas;
  10. this.autoClear = true;
  11. initGL();
  12. initProgram();
  13. this.setSize = function ( width, height ) {
  14. _canvas.width = width;
  15. _canvas.height = height;
  16. _gl.viewport( 0, 0, _canvas.width, _canvas.height );
  17. };
  18. this.clear = function () {
  19. _gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT );
  20. };
  21. this.setupLights = function ( scene ) {
  22. var l, ll, lightColor, lightPosition, lightIntensity, light;
  23. _gl.uniform1i( _program.enableLighting, scene.lights.length );
  24. for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
  25. light = scene.lights[ l ];
  26. if ( light instanceof THREE.AmbientLight ) {
  27. lightColor = light.color;
  28. _gl.uniform3f( _program.ambientLightColor, lightColor.r, lightColor.g, lightColor.b );
  29. } else if ( light instanceof THREE.DirectionalLight ) {
  30. lightColor = light.color;
  31. lightPosition = light.position;
  32. lightIntensity = light.intensity;
  33. _gl.uniform3f( _program.directionalLightDirection, lightPosition.x, lightPosition.y, lightPosition.z );
  34. _gl.uniform3f( _program.directionalLightColor, lightColor.r * lightIntensity, lightColor.g * lightIntensity, lightColor.b * lightIntensity );
  35. } else if( light instanceof THREE.PointLight ) {
  36. lightColor = light.color;
  37. lightPosition = light.position;
  38. lightIntensity = light.intensity;
  39. _gl.uniform3f( _program.pointLightPosition, lightPosition.x, lightPosition.y, lightPosition.z );
  40. _gl.uniform3f( _program.pointLightColor, lightColor.r * lightIntensity, lightColor.g * lightIntensity, lightColor.b * lightIntensity );
  41. }
  42. }
  43. };
  44. this.createBuffers = function ( object, mf ) {
  45. var f, fl, fi, face, vertexNormals, normal, uv, v1, v2, v3, v4,
  46. materialFaceGroup = object.materialFaceGroup[ mf ],
  47. faceArray = [],
  48. lineArray = [],
  49. vertexArray = [],
  50. normalArray = [],
  51. uvArray = [],
  52. vertexIndex = 0;
  53. for ( f = 0, fl = materialFaceGroup.faces.length; f < fl; f++ ) {
  54. fi = materialFaceGroup.faces[f];
  55. face = object.geometry.faces[ fi ];
  56. vertexNormals = face.vertexNormals;
  57. normal = face.normal;
  58. uv = object.geometry.uvs[ fi ];
  59. if ( face instanceof THREE.Face3 ) {
  60. v1 = object.geometry.vertices[ face.a ].position;
  61. v2 = object.geometry.vertices[ face.b ].position;
  62. v3 = object.geometry.vertices[ face.c ].position;
  63. vertexArray.push( v1.x, v1.y, v1.z );
  64. vertexArray.push( v2.x, v2.y, v2.z );
  65. vertexArray.push( v3.x, v3.y, v3.z );
  66. if ( vertexNormals.length == 3 ) {
  67. normalArray.push( vertexNormals[0].x, vertexNormals[0].y, vertexNormals[0].z );
  68. normalArray.push( vertexNormals[1].x, vertexNormals[1].y, vertexNormals[1].z );
  69. normalArray.push( vertexNormals[2].x, vertexNormals[2].y, vertexNormals[2].z );
  70. } else {
  71. normalArray.push( normal.x, normal.y, normal.z );
  72. normalArray.push( normal.x, normal.y, normal.z );
  73. normalArray.push( normal.x, normal.y, normal.z );
  74. }
  75. if ( uv ) {
  76. uvArray.push( uv[0].u, uv[0].v );
  77. uvArray.push( uv[1].u, uv[1].v );
  78. uvArray.push( uv[2].u, uv[2].v );
  79. }
  80. faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2 );
  81. // TODO: don't add lines that already exist (faces sharing edge)
  82. lineArray.push( vertexIndex, vertexIndex + 1 );
  83. lineArray.push( vertexIndex, vertexIndex + 2 );
  84. lineArray.push( vertexIndex + 1, vertexIndex + 2 );
  85. vertexIndex += 3;
  86. } else if ( face instanceof THREE.Face4 ) {
  87. v1 = object.geometry.vertices[ face.a ].position;
  88. v2 = object.geometry.vertices[ face.b ].position;
  89. v3 = object.geometry.vertices[ face.c ].position;
  90. v4 = object.geometry.vertices[ face.d ].position;
  91. vertexArray.push( v1.x, v1.y, v1.z );
  92. vertexArray.push( v2.x, v2.y, v2.z );
  93. vertexArray.push( v3.x, v3.y, v3.z );
  94. vertexArray.push( v4.x, v4.y, v4.z );
  95. if ( vertexNormals.length == 4 ) {
  96. normalArray.push( vertexNormals[0].x, vertexNormals[0].y, vertexNormals[0].z );
  97. normalArray.push( vertexNormals[1].x, vertexNormals[1].y, vertexNormals[1].z );
  98. normalArray.push( vertexNormals[2].x, vertexNormals[2].y, vertexNormals[2].z );
  99. normalArray.push( vertexNormals[3].x, vertexNormals[3].y, vertexNormals[3].z );
  100. } else {
  101. normalArray.push( normal.x, normal.y, normal.z );
  102. normalArray.push( normal.x, normal.y, normal.z );
  103. normalArray.push( normal.x, normal.y, normal.z );
  104. normalArray.push( normal.x, normal.y, normal.z );
  105. }
  106. if ( uv ) {
  107. uvArray.push( uv[0].u, uv[0].v );
  108. uvArray.push( uv[1].u, uv[1].v );
  109. uvArray.push( uv[2].u, uv[2].v );
  110. uvArray.push( uv[3].u, uv[3].v );
  111. }
  112. faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2 );
  113. faceArray.push( vertexIndex, vertexIndex + 2, vertexIndex + 3 );
  114. // TODO: don't add lines that already exist (faces sharing edge)
  115. lineArray.push( vertexIndex, vertexIndex + 1 );
  116. lineArray.push( vertexIndex, vertexIndex + 2 );
  117. lineArray.push( vertexIndex, vertexIndex + 3 );
  118. lineArray.push( vertexIndex + 1, vertexIndex + 2 );
  119. lineArray.push( vertexIndex + 2, vertexIndex + 3 );
  120. vertexIndex += 4;
  121. }
  122. }
  123. if ( !vertexArray.length ) {
  124. return;
  125. }
  126. materialFaceGroup.__webGLVertexBuffer = _gl.createBuffer();
  127. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
  128. _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW );
  129. materialFaceGroup.__webGLNormalBuffer = _gl.createBuffer();
  130. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
  131. _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW );
  132. materialFaceGroup.__webGLUVBuffer = _gl.createBuffer();
  133. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );
  134. _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( uvArray ), _gl.STATIC_DRAW );
  135. materialFaceGroup.__webGLFaceBuffer = _gl.createBuffer();
  136. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
  137. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( faceArray ), _gl.STATIC_DRAW );
  138. materialFaceGroup.__webGLLineBuffer = _gl.createBuffer();
  139. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
  140. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW );
  141. materialFaceGroup.__webGLFaceCount = faceArray.length;
  142. materialFaceGroup.__webGLLineCount = lineArray.length;
  143. };
  144. this.renderBuffer = function ( material, materialFaceGroup ) {
  145. if ( material instanceof THREE.MeshPhongMaterial ) {
  146. mAmbient = material.ambient;
  147. mDiffuse = material.diffuse;
  148. mSpecular = material.specular;
  149. _gl.uniform4f( _program.mAmbient, mAmbient.r, mAmbient.g, mAmbient.b, material.opacity );
  150. _gl.uniform4f( _program.mDiffuse, mDiffuse.r, mDiffuse.g, mDiffuse.b, material.opacity );
  151. _gl.uniform4f( _program.mSpecular, mSpecular.r, mSpecular.g, mSpecular.b, material.opacity );
  152. _gl.uniform1f( _program.mShininess, material.shininess );
  153. _gl.uniform1i( _program.material, PHONG );
  154. } else if ( material instanceof THREE.MeshColorFillMaterial ) {
  155. color = material.color;
  156. _gl.uniform4f( _program.mColor, color.r * color.a, color.g * color.a, color.b * color.a, color.a );
  157. _gl.uniform1i( _program.material, COLORFILL );
  158. } else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
  159. lineWidth = material.lineWidth;
  160. color = material.color;
  161. _gl.uniform4f( _program.mColor, color.r * color.a, color.g * color.a, color.b * color.a, color.a );
  162. _gl.uniform1i( _program.material, COLORSTROKE );
  163. } else if ( material instanceof THREE.MeshBitmapMaterial ) {
  164. if ( !material.__webGLTexture && material.loaded ) {
  165. material.__webGLTexture = _gl.createTexture();
  166. _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
  167. _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, material.bitmap ) ;
  168. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR );
  169. //_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_NEAREST );
  170. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR );
  171. _gl.generateMipmap( _gl.TEXTURE_2D );
  172. _gl.bindTexture( _gl.TEXTURE_2D, null );
  173. }
  174. _gl.activeTexture( _gl.TEXTURE0 );
  175. _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
  176. _gl.uniform1i( _program.tDiffuse, 0 );
  177. _gl.uniform1i( _program.material, BITMAP );
  178. }
  179. // vertices
  180. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
  181. _gl.vertexAttribPointer( _program.position, 3, _gl.FLOAT, false, 0, 0 );
  182. // normals
  183. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
  184. _gl.vertexAttribPointer( _program.normal, 3, _gl.FLOAT, false, 0, 0 );
  185. // uvs
  186. if ( material instanceof THREE.MeshBitmapMaterial ) {
  187. _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );
  188. _gl.enableVertexAttribArray( _program.uv );
  189. _gl.vertexAttribPointer( _program.uv, 2, _gl.FLOAT, false, 0, 0 );
  190. } else {
  191. _gl.disableVertexAttribArray( _program.uv );
  192. }
  193. // render triangles
  194. if ( material instanceof THREE.MeshBitmapMaterial ||
  195. material instanceof THREE.MeshColorFillMaterial ||
  196. material instanceof THREE.MeshPhongMaterial ) {
  197. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
  198. _gl.drawElements( _gl.TRIANGLES, materialFaceGroup.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
  199. // render lines
  200. } else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
  201. _gl.lineWidth( lineWidth );
  202. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
  203. _gl.drawElements( _gl.LINES, materialFaceGroup.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
  204. }
  205. };
  206. this.renderMesh = function ( object, camera ) {
  207. var i, l, m, ml, mf, material, meshMaterial, materialFaceGroup;
  208. // create separate VBOs per material
  209. for ( mf in object.materialFaceGroup ) {
  210. materialFaceGroup = object.materialFaceGroup[ mf ];
  211. // initialise buffers on the first access
  212. if( ! materialFaceGroup.__webGLVertexBuffer ) {
  213. this.createBuffers( object, mf );
  214. }
  215. for ( m = 0, ml = object.material.length; m < ml; m++ ) {
  216. meshMaterial = object.material[ m ];
  217. if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
  218. for ( i = 0, l = materialFaceGroup.material.length; i < l; i++ ) {
  219. material = materialFaceGroup.material[ i ];
  220. this.renderBuffer( material, materialFaceGroup );
  221. }
  222. } else {
  223. material = meshMaterial;
  224. this.renderBuffer( material, materialFaceGroup );
  225. }
  226. }
  227. }
  228. };
  229. this.setupMatrices = function ( object, camera ) {
  230. object.autoUpdateMatrix && object.updateMatrix();
  231. _modelViewMatrix.multiply( camera.matrix, object.matrix );
  232. _program.viewMatrixArray = new Float32Array( camera.matrix.flatten() );
  233. _program.modelViewMatrixArray = new Float32Array( _modelViewMatrix.flatten() );
  234. _program.projectionMatrixArray = new Float32Array( camera.projectionMatrix.flatten() );
  235. _normalMatrix = THREE.Matrix4.makeInvert3x3( _modelViewMatrix ).transpose();
  236. _program.normalMatrixArray = new Float32Array( _normalMatrix.m );
  237. _gl.uniformMatrix4fv( _program.viewMatrix, false, _program.viewMatrixArray );
  238. _gl.uniformMatrix4fv( _program.modelViewMatrix, false, _program.modelViewMatrixArray );
  239. _gl.uniformMatrix4fv( _program.projectionMatrix, false, _program.projectionMatrixArray );
  240. _gl.uniformMatrix3fv( _program.normalMatrix, false, _program.normalMatrixArray );
  241. _gl.uniformMatrix4fv( _program.objMatrix, false, new Float32Array( object.matrix.flatten() ) );
  242. };
  243. this.render = function ( scene, camera ) {
  244. var o, ol, object;
  245. if ( this.autoClear ) {
  246. this.clear();
  247. }
  248. camera.autoUpdateMatrix && camera.updateMatrix();
  249. _gl.uniform3f( _program.cameraPosition, camera.position.x, camera.position.y, camera.position.z );
  250. this.setupLights( scene );
  251. for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {
  252. object = scene.objects[ o ];
  253. this.setupMatrices( object, camera );
  254. if ( object instanceof THREE.Mesh ) {
  255. this.renderMesh( object, camera );
  256. } else if ( object instanceof THREE.Line ) {
  257. // TODO
  258. // It would be very inefficient to do lines one-by-one.
  259. // This will need a complete redesign from how CanvasRenderer does it.
  260. // Though it could be brute forced, if only used for lightweight
  261. // stuff (as CanvasRenderer can only handle small number of elements
  262. // anyways).
  263. // Heavy-duty wireframe lines are handled efficiently in mesh renderer.
  264. } else if ( object instanceof THREE.Particle ) {
  265. // TODO
  266. // The same as with lines, particles shouldn't be handled one-by-one.
  267. // Again, heavy duty particle system would require different approach,
  268. // like one VBO per particle system and then update attribute arrays,
  269. // though the best would be to move also behavior computation
  270. // into the shader (ala http://spidergl.org/example.php?id=11)
  271. }
  272. }
  273. };
  274. function initGL() {
  275. try {
  276. _gl = _canvas.getContext( 'experimental-webgl', { antialias: true} );
  277. } catch(e) { }
  278. if (!_gl) {
  279. alert("WebGL not supported");
  280. throw "cannot create webgl context";
  281. }
  282. _gl.clearColor( 0, 0, 0, 1 );
  283. _gl.clearDepth( 1 );
  284. _gl.enable( _gl.DEPTH_TEST );
  285. _gl.depthFunc( _gl.LEQUAL );
  286. _gl.enable( _gl.BLEND );
  287. //_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
  288. // _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE ); // cool!
  289. _gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
  290. _gl.clearColor( 0, 0, 0, 0 );
  291. }
  292. function initProgram() {
  293. _program = _gl.createProgram();
  294. _gl.attachShader( _program, getShader( "fragment", [
  295. "#ifdef GL_ES",
  296. "precision highp float;",
  297. "#endif",
  298. "uniform int material;", // 0 - ColorFill, 1 - ColorStroke, 2 - Bitmap, 3 - Phong
  299. "uniform sampler2D tDiffuse;",
  300. "uniform vec4 mColor;",
  301. "uniform vec4 mAmbient;",
  302. "uniform vec4 mDiffuse;",
  303. "uniform vec4 mSpecular;",
  304. "uniform float mShininess;",
  305. "varying vec3 vNormal;",
  306. "varying vec2 vUv;",
  307. "varying vec3 vLightWeighting;",
  308. "varying vec3 vPointLightVector;",
  309. "varying vec3 vDirectionalLightVector;",
  310. "varying vec3 vViewPosition;",
  311. "void main() {",
  312. // Blinn-Phong
  313. // based on o3d example
  314. "if ( material == 3 ) { ",
  315. "vec3 normal = normalize( vNormal );",
  316. "vec3 viewPosition = normalize( vViewPosition );",
  317. // point light
  318. "vec3 pointVector = normalize( vPointLightVector );",
  319. "vec3 pointHalfVector = normalize( vPointLightVector + vViewPosition );",
  320. "float pointDotNormalHalf = dot( normal, pointHalfVector );",
  321. "float pointAmbientWeight = 1.0;",
  322. "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
  323. // Ternary conditional is from the original o3d shader. Here it produces abrupt dark cutoff artefacts.
  324. // Using just pow works ok in Chrome, but makes different artefact in Firefox 4.
  325. // Zeroing on negative pointDotNormalHalf seems to work in both.
  326. //"float specularCompPoint = dot( normal, pointVector ) < 0.0 || pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );",
  327. //"float specularCompPoint = pow( pointDotNormalHalf, mShininess );",
  328. "float pointSpecularWeight = pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );",
  329. "vec4 pointAmbient = mAmbient * pointAmbientWeight;",
  330. "vec4 pointDiffuse = mDiffuse * pointDiffuseWeight;",
  331. "vec4 pointSpecular = mSpecular * pointSpecularWeight;",
  332. // directional light
  333. "vec3 dirVector = normalize( vDirectionalLightVector );",
  334. "vec3 dirHalfVector = normalize( vDirectionalLightVector + vViewPosition );",
  335. "float dirDotNormalHalf = dot( normal, dirHalfVector );",
  336. "float dirAmbientWeight = 1.0;",
  337. "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
  338. "float dirSpecularWeight = dirDotNormalHalf < 0.0 ? 0.0 : pow( dirDotNormalHalf, mShininess );",
  339. "vec4 dirAmbient = mAmbient * dirAmbientWeight;",
  340. "vec4 dirDiffuse = mDiffuse * dirDiffuseWeight;",
  341. "vec4 dirSpecular = mSpecular * dirSpecularWeight;",
  342. // light contribution summation
  343. "vec4 totalLight = vec4( 0.0, 0.0, 0.0, 1.0 );",
  344. "totalLight += pointAmbient + pointDiffuse + pointSpecular;",
  345. "totalLight += dirAmbient + dirDiffuse + dirSpecular;",
  346. // looks nicer with weighting
  347. "gl_FragColor = vec4( totalLight.xyz * vLightWeighting, 1.0 );",
  348. //"gl_FragColor = vec4( totalLight.xyz, 1.0 );",
  349. // Bitmap: texture
  350. "} else if ( material==2 ) {",
  351. "vec4 texelColor = texture2D( tDiffuse, vUv );",
  352. "gl_FragColor = vec4( texelColor.rgb * vLightWeighting, texelColor.a );",
  353. // ColorStroke: wireframe using uniform color
  354. "} else if ( material == 1 ) {",
  355. "gl_FragColor = vec4( mColor.rgb * vLightWeighting, mColor.a );",
  356. // ColorFill: triangle using uniform color
  357. "} else {",
  358. "gl_FragColor = vec4( mColor.rgb * vLightWeighting, mColor.a );",
  359. //"gl_FragColor = vec4( vNormal, 1.0 );",
  360. "}",
  361. "}"].join("\n") ) );
  362. _gl.attachShader( _program, getShader( "vertex", [
  363. "attribute vec3 position;",
  364. "attribute vec3 normal;",
  365. "attribute vec2 uv;",
  366. "uniform vec3 cameraPosition;",
  367. "uniform bool enableLighting;",
  368. "uniform vec3 ambientLightColor;",
  369. "uniform vec3 directionalLightColor;",
  370. "uniform vec3 directionalLightDirection;",
  371. "uniform vec3 pointLightColor;",
  372. "uniform vec3 pointLightPosition;",
  373. "uniform mat4 objMatrix;",
  374. "uniform mat4 viewMatrix;",
  375. "uniform mat4 modelViewMatrix;",
  376. "uniform mat4 projectionMatrix;",
  377. "uniform mat3 normalMatrix;",
  378. "varying vec3 vNormal;",
  379. "varying vec2 vUv;",
  380. "varying vec3 vLightWeighting;",
  381. "varying vec3 vPointLightVector;",
  382. "varying vec3 vDirectionalLightVector;",
  383. "varying vec3 vViewPosition;",
  384. "void main(void) {",
  385. // eye space
  386. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
  387. "vec3 transformedNormal = normalize( normalMatrix * normal );",
  388. "vec4 lPosition = viewMatrix * vec4( pointLightPosition, 1.0 );",
  389. "vec4 lDirection = viewMatrix * vec4( directionalLightDirection, 0.0 );",
  390. "vPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );",
  391. "vDirectionalLightVector = normalize( lDirection.xyz );",
  392. // world space
  393. "vec4 mPosition = objMatrix * vec4( position, 1.0 );",
  394. "vViewPosition = cameraPosition - mPosition.xyz;",
  395. "if( !enableLighting ) {",
  396. "vLightWeighting = vec3( 1.0, 1.0, 1.0 );",
  397. "} else {",
  398. "float directionalLightWeighting = max( dot( transformedNormal, normalize(lDirection.xyz ) ), 0.0 );",
  399. "float pointLightWeighting = max( dot( transformedNormal, vPointLightVector ), 0.0 );",
  400. "vLightWeighting = ambientLightColor + directionalLightColor * directionalLightWeighting + pointLightColor * pointLightWeighting;",
  401. "}",
  402. "vNormal = transformedNormal;",
  403. "vUv = uv;",
  404. "gl_Position = projectionMatrix * mvPosition;",
  405. "}"].join("\n") ) );
  406. _gl.linkProgram( _program );
  407. if ( !_gl.getProgramParameter( _program, _gl.LINK_STATUS ) ) {
  408. alert( "Could not initialise shaders" );
  409. }
  410. _gl.useProgram( _program );
  411. // matrices
  412. _program.viewMatrix = _gl.getUniformLocation( _program, "viewMatrix" );
  413. _program.modelViewMatrix = _gl.getUniformLocation( _program, "modelViewMatrix" );
  414. _program.projectionMatrix = _gl.getUniformLocation( _program, "projectionMatrix" );
  415. _program.normalMatrix = _gl.getUniformLocation( _program, "normalMatrix" );
  416. _program.objMatrix = _gl.getUniformLocation( _program, "objMatrix" );
  417. _program.cameraPosition = _gl.getUniformLocation(_program, 'cameraPosition');
  418. // lights
  419. _program.enableLighting = _gl.getUniformLocation(_program, 'enableLighting');
  420. _program.ambientLightColor = _gl.getUniformLocation(_program, 'ambientLightColor');
  421. _program.directionalLightColor = _gl.getUniformLocation(_program, 'directionalLightColor');
  422. _program.directionalLightDirection = _gl.getUniformLocation(_program, 'directionalLightDirection');
  423. _program.pointLightColor = _gl.getUniformLocation(_program, 'pointLightColor');
  424. _program.pointLightPosition = _gl.getUniformLocation(_program, 'pointLightPosition');
  425. // material
  426. _program.material = _gl.getUniformLocation(_program, 'material');
  427. // material properties (ColorFill / ColorStroke shader)
  428. _program.mColor = _gl.getUniformLocation(_program, 'mColor');
  429. // material properties (Blinn-Phong shader)
  430. _program.mAmbient = _gl.getUniformLocation(_program, 'mAmbient');
  431. _program.mDiffuse = _gl.getUniformLocation(_program, 'mDiffuse');
  432. _program.mSpecular = _gl.getUniformLocation(_program, 'mSpecular');
  433. _program.mShininess = _gl.getUniformLocation(_program, 'mShininess');
  434. // texture (Bitmap shader)
  435. _program.tDiffuse = _gl.getUniformLocation( _program, "tDiffuse");
  436. _gl.uniform1i( _program.tDiffuse, 0 );
  437. // vertex arrays
  438. _program.position = _gl.getAttribLocation( _program, "position" );
  439. _gl.enableVertexAttribArray( _program.position );
  440. _program.normal = _gl.getAttribLocation( _program, "normal" );
  441. _gl.enableVertexAttribArray( _program.normal );
  442. _program.uv = _gl.getAttribLocation( _program, "uv" );
  443. _gl.enableVertexAttribArray( _program.uv );
  444. _program.viewMatrixArray = new Float32Array(16);
  445. _program.modelViewMatrixArray = new Float32Array(16);
  446. _program.projectionMatrixArray = new Float32Array(16);
  447. }
  448. function getShader( type, string ) {
  449. var shader;
  450. if ( type == "fragment" ) {
  451. shader = _gl.createShader( _gl.FRAGMENT_SHADER );
  452. } else if ( type == "vertex" ) {
  453. shader = _gl.createShader( _gl.VERTEX_SHADER );
  454. }
  455. _gl.shaderSource( shader, string );
  456. _gl.compileShader( shader );
  457. if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
  458. alert( _gl.getShaderInfoLog( shader ) );
  459. return null;
  460. }
  461. return shader;
  462. }
  463. };