TeapotPerPixel.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <!DOCTYPE html>
  2. <!--
  3. /*
  4. * Copyright (C) 2009 Apple Inc. All Rights Reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  16. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  18. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  19. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  21. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  22. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  23. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. -->
  28. <html>
  29. <head>
  30. <title>Teapot (per-pixel)</title>
  31. <script src="resources/J3DI.js"> </script>
  32. <script src="resources/J3DIMath.js" type="text/javascript"> </script>
  33. <script id="vshader" type="x-shader/x-vertex">
  34. /*
  35. Copyright (c) 2008 Seneca College
  36. Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  37. */
  38. // We need to create our own light structure since we can't access
  39. // the light() function in the 2.0 context.
  40. struct Light
  41. {
  42. vec4 ambient;
  43. vec4 diffuse;
  44. vec4 specular;
  45. vec4 position;
  46. vec3 halfVector;
  47. };
  48. struct Material
  49. {
  50. vec4 emission;
  51. vec4 ambient;
  52. vec4 diffuse;
  53. vec4 specular;
  54. float shininess;
  55. };
  56. //
  57. // vertex attributes
  58. //
  59. attribute vec4 a_vertex;
  60. attribute vec3 a_normal;
  61. attribute vec4 a_texCoord;
  62. // for every model we multiply the projection, view and model matrices
  63. // once to prevent having to do it for every vertex, however we still need
  64. // the view matrix to calculate lighting.
  65. uniform mat4 u_modelViewMatrix;
  66. // we can calculate this once per model to speed up processing done on the js side.
  67. uniform mat4 u_modelViewProjMatrix;
  68. // matrix to transform the vertex normals
  69. uniform mat4 u_normalMatrix;
  70. // custom light structures need to be used since we don't have access to
  71. // light states.
  72. uniform Light u_light;
  73. // material
  74. uniform vec4 u_globalAmbientColor;
  75. uniform Material u_frontMaterial;
  76. uniform Material u_backMaterial;
  77. // passed to fragment shader
  78. varying vec4 v_diffuse, v_ambient;
  79. varying vec3 v_normal, v_lightDir;
  80. varying vec2 v_texCoord;
  81. /*
  82. Given a reference to the ambient and diffuse lighting variables,
  83. this function will calculate how much each component contributes to the scene.
  84. Light light - the light in view space
  85. vec3 normal -
  86. vec4 ambient -
  87. vec4 diffuse -
  88. */
  89. vec3 directionalLight(inout vec4 ambient, inout vec4 diffuse)
  90. {
  91. ambient += u_light.ambient;
  92. diffuse += u_light.diffuse;
  93. return normalize(vec3(u_light.position));
  94. }
  95. void main()
  96. {
  97. v_normal = normalize(u_normalMatrix * vec4(a_normal, 1)).xyz;
  98. vec4 ambient = vec4(0.0, 0.0, 0.0, 1.0);
  99. vec4 diffuse = vec4(0.0, 0.0, 0.0, 1.0);
  100. vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
  101. // place the current vertex into view space
  102. // ecPos = eye coordinate position.
  103. vec4 ecPos4 = u_modelViewMatrix * a_vertex;
  104. // the current vertex in eye coordinate space
  105. vec3 ecPos = ecPos4.xyz/ecPos4.w;
  106. v_lightDir = directionalLight(ambient, diffuse);
  107. v_ambient = u_frontMaterial.ambient * ambient;
  108. v_ambient += u_globalAmbientColor * u_frontMaterial.ambient;
  109. v_diffuse = u_frontMaterial.diffuse * diffuse;
  110. gl_Position = u_modelViewProjMatrix * a_vertex;
  111. v_texCoord = a_texCoord.st;
  112. }
  113. </script>
  114. <script id="fshader" type="x-shader/x-fragment">
  115. #ifdef GL_ES
  116. precision mediump float;
  117. #endif
  118. struct Light
  119. {
  120. vec4 ambient;
  121. vec4 diffuse;
  122. vec4 specular;
  123. vec4 position;
  124. vec3 halfVector;
  125. };
  126. struct Material
  127. {
  128. vec4 emission;
  129. vec4 ambient;
  130. vec4 diffuse;
  131. vec4 specular;
  132. float shininess;
  133. };
  134. uniform sampler2D u_sampler2d;
  135. uniform Light u_light;
  136. uniform Material u_frontMaterial;
  137. uniform Material u_backMaterial;
  138. varying vec4 v_diffuse, v_ambient;
  139. varying vec3 v_normal, v_lightDir;
  140. varying vec2 v_texCoord;
  141. void main()
  142. {
  143. vec4 color = v_diffuse;
  144. vec3 n = normalize(v_normal);
  145. Light light = u_light;
  146. vec3 lightDir = v_lightDir;
  147. float nDotL = max(dot(n, lightDir), 0.0);
  148. if (nDotL > 0.0) {
  149. color = vec4(color.rgb * nDotL, color.a);
  150. float nDotHV = max(dot(n, light.halfVector), 0.0);
  151. vec4 specular = u_frontMaterial.specular * light.specular;
  152. color += vec4(specular.rgb * pow(nDotHV, u_frontMaterial.shininess), specular.a);
  153. }
  154. gl_FragColor = color + v_ambient;
  155. }
  156. </script>
  157. <script>
  158. function setDirectionalLight(ctx, program, eyeVector, direction, ambient, diffuse, specular)
  159. {
  160. var lightString = "u_light.";
  161. ctx.uniform4f(ctx.getUniformLocation(program, lightString+"ambient"),
  162. ambient[0], ambient[1], ambient[2], ambient[3]);
  163. ctx.uniform4f(ctx.getUniformLocation(program, lightString+"diffuse"),
  164. diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
  165. ctx.uniform4f(ctx.getUniformLocation(program, lightString+"specular"),
  166. specular[0], specular[1], specular[2], specular[3]);
  167. ctx.uniform4f(ctx.getUniformLocation(program, lightString+"position"),
  168. direction[0], direction[1], direction[2], direction[3]);
  169. // compute the half vector
  170. var halfVector = [ eyeVector[0] + direction[0], eyeVector[1] + direction[1], eyeVector[2] + direction[2] ];
  171. var length = Math.sqrt(halfVector[0] * halfVector[0] +
  172. halfVector[1] * halfVector[1] +
  173. halfVector[2] * halfVector[2]);
  174. if (length == 0)
  175. halfVector = [ 0, 0, 1 ];
  176. else {
  177. halfVector[0] /= length;
  178. halfVector[1] /= length;
  179. halfVector[2] /= length;
  180. }
  181. ctx.uniform3f(ctx.getUniformLocation(program, lightString+"halfVector"),
  182. halfVector[0], halfVector[1], halfVector[2]);
  183. }
  184. function setMaterial(ctx, program, emission, ambient, diffuse, specular, shininess)
  185. {
  186. var matString = "u_frontMaterial.";
  187. ctx.uniform4f(ctx.getUniformLocation(program, matString+"emission"),
  188. emission[0], emission[1], emission[2], emission[3]);
  189. ctx.uniform4f(ctx.getUniformLocation(program, matString+"ambient"),
  190. ambient[0], ambient[1], ambient[2], ambient[3]);
  191. ctx.uniform4f(ctx.getUniformLocation(program, matString+"diffuse"),
  192. diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
  193. ctx.uniform4f(ctx.getUniformLocation(program, matString+"specular"),
  194. specular[0], specular[1], specular[2], specular[3]);
  195. ctx.uniform1f(ctx.getUniformLocation(program, matString+"shininess"), shininess);
  196. }
  197. function init()
  198. {
  199. var gl = initWebGL("example", "vshader", "fshader",
  200. [ "a_normal", "a_texCoord", "a_vertex"],
  201. [ 0, 0, 0, 1 ], 10000);
  202. gl.uniform1i(gl.getUniformLocation(gl.program, "u_sampler2d"), 0);
  203. gl.uniform4f(gl.getUniformLocation(gl.program, "u_globalAmbientColor"), 0.2, 0.2, 0.2, 1);
  204. setDirectionalLight(gl, gl.program,
  205. [ 0, 0, 1 ], // eyeVector
  206. [0, 0, 1, 1], // position
  207. [0.1, 0.1, 0.1, 1], // ambient
  208. [1, 1, 1, 1], // diffuse
  209. [1, 1, 1, 1]); // specular
  210. setMaterial(gl, gl.program,
  211. [ 0, 0, 0, 0 ], // emission
  212. [ 0.1, 0.1, 0.1, 1 ], // ambient
  213. [ 0.8, 0.2, 0, 1 ], // diffuse
  214. [ 0, 0, 1, 1 ], // specular
  215. 32); // shininess
  216. obj = loadObj(gl, "resources/teapot.obj");
  217. mvMatrix = new J3DIMatrix4();
  218. normalMatrix = new J3DIMatrix4();
  219. return gl;
  220. }
  221. width = -1;
  222. height = -1;
  223. loaded = false;
  224. function reshape(ctx)
  225. {
  226. var canvas = document.getElementById('example');
  227. if (canvas.width == width && canvas.height == height)
  228. return;
  229. width = canvas.width;
  230. height = canvas.height;
  231. ctx.viewport(0, 0, width, height);
  232. ctx.perspectiveMatrix = new J3DIMatrix4();
  233. ctx.perspectiveMatrix.perspective(30, width/height, 1, 10000);
  234. ctx.perspectiveMatrix.lookat(0,0,50, 0, 0, 0, 0, 1, 0);
  235. }
  236. function drawPicture(ctx)
  237. {
  238. var startRenderTime = new Date().getTime();
  239. reshape(ctx);
  240. ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
  241. if (!loaded && obj.loaded) {
  242. loaded = true;
  243. ctx.enableVertexAttribArray(0);
  244. ctx.enableVertexAttribArray(1);
  245. ctx.enableVertexAttribArray(2);
  246. ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.vertexObject);
  247. ctx.vertexAttribPointer(2, 3, ctx.FLOAT, false, 0, 0);
  248. ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.normalObject);
  249. ctx.vertexAttribPointer(0, 3, ctx.FLOAT, false, 0, 0);
  250. ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.texCoordObject);
  251. ctx.vertexAttribPointer(1, 2, ctx.FLOAT, false, 0, 0);
  252. ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, obj.indexObject);
  253. }
  254. if (!loaded)
  255. return;
  256. // generate the model-view matrix
  257. mvMatrix.makeIdentity();
  258. mvMatrix.rotate(10, 1,0,0);
  259. mvMatrix.rotate(currentAngle, 0, 1, 0);
  260. mvMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewMatrix"), false);
  261. // construct the normal matrix from the model-view matrix
  262. normalMatrix.load(mvMatrix);
  263. normalMatrix.invert();
  264. normalMatrix.transpose();
  265. normalMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_normalMatrix"), false);
  266. // Construct the model-view * projection matrix and pass it in
  267. var mvpMatrix = new J3DIMatrix4();
  268. mvpMatrix.load(ctx.perspectiveMatrix);
  269. mvpMatrix.multiply(mvMatrix);
  270. mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false);
  271. ctx.drawElements(ctx.TRIANGLES, obj.numIndices, ctx.UNSIGNED_SHORT, 0);
  272. ctx.flush();
  273. framerate.snapshot();
  274. currentAngle += incAngle;
  275. if (currentAngle > 360)
  276. currentAngle -= 360;
  277. }
  278. function start()
  279. {
  280. var c = document.getElementById("example");
  281. var w = Math.floor(window.innerWidth * 0.9);
  282. var h = Math.floor(window.innerHeight * 0.9);
  283. c.width = w;
  284. c.height = h;
  285. var ctx = init();
  286. currentAngle = 0;
  287. incAngle = 0.2;
  288. framerate = new Framerate("framerate");
  289. var f = function() { drawPicture(ctx) };
  290. setInterval(f, 10);
  291. }
  292. </script>
  293. <style type="text/css">
  294. canvas {
  295. border: 2px solid black;
  296. }
  297. </style>
  298. </head>
  299. <body onload="start()">
  300. <canvas id="example">
  301. There is supposed to be an example drawing here, but it's not important.
  302. </canvas>
  303. <div id="framerate"></div>
  304. </body>
  305. </html>