Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.66 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <meta charset="UTF-8">
  3. <html>
  4. <head>
  5. <title>CS424, Fall 2017, Lab 12</title>
  6. <style>
  7. body {
  8. background-color: #EEEEEE;
  9. }
  10. label {
  11. white-space: pre;
  12. margin-left: 25px;
  13. }
  14. </style>
  15.  
  16.  
  17. <script type="x-shader/x-vertex" id="vshader-source">
  18. attribute vec3 a_coords;
  19. attribute vec3 a_normal;
  20. uniform mat4 modelview;
  21. uniform mat4 projection;
  22. varying vec3 v_normal;
  23. varying vec3 v_eyeCoords;
  24. void main() {
  25. vec4 coords = vec4(a_coords,1.0);
  26. vec4 eyeCoords = modelview * coords;
  27. gl_Position = projection * eyeCoords;
  28. v_normal = normalize(a_normal);
  29. v_eyeCoords = eyeCoords.xyz/eyeCoords.w;
  30. }
  31. </script>
  32.  
  33. <script type="x-shader/x-fragment" id="fshader-source">
  34. #ifdef GL_FRAGMENT_PRECISION_HIGH
  35. precision highp float;
  36. #else
  37. precision mediump float;
  38. #endif
  39. struct MaterialProperties {
  40. vec3 diffuseColor; // diffuseColor.a is alpha for the fragment
  41. vec3 specularColor;
  42. vec3 emissiveColor;
  43. float specularExponent;
  44. };
  45. struct LightProperties {
  46. bool enabled;
  47. vec4 position;
  48. vec3 color;
  49. };
  50. uniform MaterialProperties material; // do two-sided lighting, but assume front and back materials are the same
  51. uniform LightProperties lights[4];
  52. uniform mat3 normalMatrix;
  53. varying vec3 v_normal;
  54. varying vec3 v_eyeCoords;
  55. vec3 lightingEquation( LightProperties light, MaterialProperties material,
  56. vec3 eyeCoords, vec3 N, vec3 V ) {
  57. // N is normal vector, V is direction to viewer.
  58. vec3 L, R; // Light direction and reflected light direction.
  59. if ( light.position.w == 0.0 ) {
  60. L = normalize( light.position.xyz );
  61. }
  62. else {
  63. L = normalize( light.position.xyz/light.position.w - v_eyeCoords );
  64. }
  65. if (dot(L,N) <= 0.0) {
  66. return vec3(0.0);
  67. }
  68. vec3 reflection = dot(L,N) * light.color * material.diffuseColor;
  69. R = -reflect(L,N);
  70. if (dot(R,V) > 0.0) {
  71. float factor = pow(dot(R,V),material.specularExponent);
  72. reflection += factor * material.specularColor * light.color;
  73. }
  74. return reflection;
  75. }
  76. void main() {
  77. vec3 normal = normalize( normalMatrix*v_normal );
  78. vec3 viewDirection = normalize( -v_eyeCoords); // (Assumes a perspective projection.)
  79. vec3 color = material.emissiveColor;
  80. for (int i = 0; i < 4; i++) {
  81. if (lights[i].enabled) {
  82. if (gl_FrontFacing) {
  83. color += lightingEquation( lights[i], material, v_eyeCoords,
  84. normal, viewDirection);
  85. }
  86. else {
  87. color += lightingEquation( lights[i], material, v_eyeCoords,
  88. -normal, viewDirection);
  89. }
  90. }
  91. }
  92. gl_FragColor = vec4(color, 1);
  93. }
  94. </script>
  95.  
  96.  
  97. <script src="gl-matrix.js"></script>
  98. <script src="basic-object-models-IFS.js"></script>
  99. <script src="teapot-model-IFS.js"></script>
  100. <script>
  101.  
  102. "use strict";
  103.  
  104. var gl; // The webgl context
  105. var canvas; // The canvas where gl draws
  106.  
  107. var a_coords_loc; // Location of the a_coords attribute variable in the shader program
  108. var a_normal_loc; // Location of a_normal attribute
  109.  
  110. var u_modelview; // Locations for uniform matrices
  111. var u_projection;
  112. var u_normalMatrix;
  113.  
  114. var u_material; // An object tolds uniform locations for the material.
  115. var u_lights; // An array of objects that holds uniform locations for light properties.
  116.  
  117. var projection = mat4.create(); // projection matrix
  118. var modelview = mat4.create(); // modelview matrix
  119. var normalMatrix = mat3.create(); // matrix for transforming normal vectors
  120.  
  121. var rotationMatrix = mat4.create();
  122.  
  123. var frameNumber = 0; // frame number during animation
  124.  
  125. var cone, cylinder, cube; // Basic objects, created using function createModel and basic-object-models-IFS.js.
  126. // The cube is 1 unit on each side and is centered at (0,0,0).
  127. // the cone and cylinder have diameter 1 and height 1 and are centered at
  128. // (0,0,0), with their axes aligned along the z-axis.
  129.  
  130. var matrixStack = []; // A stack of matrices for implementing hierarchical graphics
  131.  
  132. var currentColor = [1,1,1]; // The current diffuse color; render() functions in the basic objects set
  133. // the diffuse color to currentColor when it is called before drawing the object
  134. // Specular color properties, which don't change, are set in initGL()
  135.  
  136. var rotateX = 0, rotateY = 0; // Overal rotation of model, in radians, set by mouse dragging.
  137. var angle = 0;
  138. /**
  139. * Draws the image, which consists of either the "world" or a closeup of the "car".
  140. */
  141.  
  142. function drawWind(){
  143. pushMatrix();
  144. mat4.rotateY(modelview,modelview, Math.PI * 0.5);
  145. mat4.scale(modelview,modelview,[1, 1, 4]);
  146. cone.render();
  147. popMatrix();
  148.  
  149. pushMatrix();
  150. mat4.translate(modelview, modelview, [-2.5, 0, 0])
  151. mat4.rotateY(modelview,modelview, Math.PI * 0.5);
  152. mat4.rotateX(modelview,modelview, Math.PI);
  153. cone.render();
  154. popMatrix();
  155. }
  156.  
  157. function drawWindmill(){
  158. pushMatrix()
  159. mat4.translate(modelview, modelview, [-5.3, 0.3, 0])
  160. mat4.rotateZ(modelview,modelview, Math.PI * 0.20);
  161. mat4.rotateY(modelview,modelview, Math.PI);
  162. drawWind();
  163. popMatrix();
  164.  
  165. pushMatrix()
  166. mat4.translate(modelview, modelview, [-0.45, 0.25, 0])
  167. mat4.rotateZ(modelview,modelview, 0.80 * Math.PI);
  168. mat4.rotateY(modelview,modelview, Math.PI);
  169. drawWind();
  170. popMatrix();
  171.  
  172. pushMatrix()
  173. mat4.translate(modelview, modelview, [-2.9, 5, 0])
  174. mat4.rotateZ(modelview,modelview, Math.PI * 1.5);
  175. mat4.rotateY(modelview,modelview, Math.PI);
  176. drawWind();
  177. popMatrix();
  178. }
  179.  
  180. function drawWM(){
  181. pushMatrix();
  182. currentColor = [1, 1, 0];
  183. mat4.translate(modelview, modelview, [0, 0, -0.3])
  184. mat4.rotateX(modelview,modelview, Math.PI * 0.5);
  185. mat4.scale(modelview,modelview,[0.5, 0.5, 9]);
  186. cylinder.render();
  187. popMatrix();
  188.  
  189. pushMatrix();
  190. currentColor = [0.3, 0.4, 0.2];
  191. mat4.translate(modelview, modelview, [-2.9, 2, 0])
  192. pushMatrix();
  193. mat4.translate(modelview, modelview, [2.9, 2, 0])
  194. mat4.rotate(modelview, modelview, angle, [0, 0, 1]);
  195. mat4.translate(modelview, modelview, [2.9, -2, 0])
  196. drawWindmill();
  197. popMatrix();
  198. popMatrix();
  199. }
  200.  
  201. function drawBox(){
  202. pushMatrix()
  203. currentColor = [0.9, 0.6, 0.137];
  204. mat4.translate(modelview, modelview, [0, -4, -0.4])
  205. mat4.scale(modelview,modelview,[6, 1, 6]);
  206. cube.render();
  207. popMatrix();
  208. }
  209.  
  210. function draw() {
  211. gl.clearColor(0,0,0,1);
  212. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  213.  
  214. mat4.perspective(projection, Math.PI/4, 1, 1, 50);
  215. gl.uniformMatrix4fv(u_projection, false, projection );
  216.  
  217. mat4.lookAt(modelview, [0,0,25], [0,0,0], [0,1,0]);
  218.  
  219. mat4.rotateX(modelview,modelview,rotateX);
  220. mat4.rotateY(modelview,modelview,rotateY);
  221.  
  222. drawWM();
  223. drawBox();
  224.  
  225.  
  226. pushMatrix();
  227. currentColor = [0.123, 0.222, 0.985];
  228. mat4.translate(modelview, modelview, [2, -2.8, 0.5]);
  229. mat4.scale(modelview, modelview, [0.1, 0.1, 0.1]);
  230. teapot.render();
  231. popMatrix();
  232.  
  233. angle += Math.PI * 0.01;
  234.  
  235. currentColor = [1, 0.6, 1]; // light magenta
  236. } // end draw();
  237.  
  238.  
  239. /**
  240. * Push a copy of the current modelview matrix onto the matrix stack.
  241. */
  242. function pushMatrix() {
  243. matrixStack.push( mat4.clone(modelview) );
  244. }
  245.  
  246.  
  247. /**
  248. * Restore the modelview matrix to a value popped from the matrix stack.
  249. */
  250. function popMatrix() {
  251. modelview = matrixStack.pop();
  252. }
  253.  
  254.  
  255. /**
  256. * Create one of the basic objects. The modelData holds the data for
  257. * an IFS using the structure from basic-object-models-IFS.js. This function
  258. * creates VBOs to hold the coordinates, normal vectors, and indices
  259. * from the IFS, and it loads the data into those buffers. The function
  260. * creates a new object whose properties are the identities of the
  261. * VBOs. The new object also has a function, render(), that can be called to
  262. * render the object, using all the data from the buffers. That object
  263. * is returned as the value of the function. (The second parameter,
  264. * xtraTranslate, is there because this program was ported from a Java
  265. * version where cylinders were created in a different position, with
  266. * the base on the xy-plane instead of with their center at the origin.
  267. * The xtraTranslate parameter is a 3-vector that is applied as a
  268. * translation to the rendered object. It is used to move the cylinders
  269. * into the position expected by the code that was ported from Java.)
  270. */
  271. function createModel(modelData) {
  272. var model = {};
  273. model.coordsBuffer = gl.createBuffer();
  274. model.normalBuffer = gl.createBuffer();
  275. model.indexBuffer = gl.createBuffer();
  276. model.count = modelData.indices.length;
  277. gl.bindBuffer(gl.ARRAY_BUFFER, model.coordsBuffer);
  278. gl.bufferData(gl.ARRAY_BUFFER, modelData.vertexPositions, gl.STATIC_DRAW);
  279. gl.bindBuffer(gl.ARRAY_BUFFER, model.normalBuffer);
  280. gl.bufferData(gl.ARRAY_BUFFER, modelData.vertexNormals, gl.STATIC_DRAW);
  281. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
  282. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, modelData.indices, gl.STATIC_DRAW);
  283. model.render = function() { // This function will render the object.
  284. // Since the buffer from which we are taking the coordinates and normals
  285. // changes each time an object is drawn, we have to use gl.vertexAttribPointer
  286. // to specify the location of the data. And to do that, we must first
  287. // bind the buffer that contains the data. Similarly, we have to
  288. // bind this object's index buffer before calling gl.drawElements.
  289. gl.bindBuffer(gl.ARRAY_BUFFER, this.coordsBuffer);
  290. gl.vertexAttribPointer(a_coords_loc, 3, gl.FLOAT, false, 0, 0);
  291. gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);
  292. gl.vertexAttribPointer(a_normal_loc, 3, gl.FLOAT, false, 0, 0);
  293. gl.uniform3fv(u_material.diffuseColor, currentColor);
  294. gl.uniformMatrix4fv(u_modelview, false, modelview );
  295. mat3.normalFromMat4(normalMatrix, modelview);
  296. gl.uniformMatrix3fv(u_normalMatrix, false, normalMatrix);
  297. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  298. gl.drawElements(gl.TRIANGLES, this.count, gl.UNSIGNED_SHORT, 0);
  299. if (this.xtraTranslate) {
  300. popMatrix();
  301. }
  302. }
  303. return model;
  304. }
  305.  
  306.  
  307. /**
  308. * Creates a program for use in the WebGL context gl, and returns the
  309. * identifier for that program. If an error occurs while compiling or
  310. * linking the program, an exception of type String is thrown. The error
  311. * string contains the compilation or linking error. If no error occurs,
  312. * the program identifier is the return value of the function.
  313. * The second and third parameters are the id attributes for <script>
  314. * elements that contain the source code for the vertex and fragment
  315. * shaders.
  316. * If the third parameter is present, it should be the name of an
  317. * attribute variable in the shader program, and the attribute should be
  318. * one that is always used. The attribute will be assigned attribute
  319. * number 0. This is done because it is suggested that there should
  320. * always be an attribute number 0 in use.
  321. */
  322. function createProgram(gl, vertexShaderID, fragmentShaderID, attribute0) {
  323. function getTextContent( elementID ) {
  324. // This nested function retrieves the text content of an
  325. // element on the web page. It is used here to get the shader
  326. // source code from the script elements that contain it.
  327. var element = document.getElementById(elementID);
  328. var node = element.firstChild;
  329. var str = "";
  330. while (node) {
  331. if (node.nodeType == 3) // this is a text node
  332. str += node.textContent;
  333. node = node.nextSibling;
  334. }
  335. return str;
  336. }
  337. try {
  338. var vertexShaderSource = getTextContent( vertexShaderID );
  339. var fragmentShaderSource = getTextContent( fragmentShaderID );
  340. }
  341. catch (e) {
  342. throw "Error: Could not get shader source code from script elements.";
  343. }
  344. var vsh = gl.createShader( gl.VERTEX_SHADER );
  345. gl.shaderSource(vsh,vertexShaderSource);
  346. gl.compileShader(vsh);
  347. if ( ! gl.getShaderParameter(vsh, gl.COMPILE_STATUS) ) {
  348. throw "Error in vertex shader: " + gl.getShaderInfoLog(vsh);
  349. }
  350. var fsh = gl.createShader( gl.FRAGMENT_SHADER );
  351. gl.shaderSource(fsh, fragmentShaderSource);
  352. gl.compileShader(fsh);
  353. if ( ! gl.getShaderParameter(fsh, gl.COMPILE_STATUS) ) {
  354. throw "Error in fragment shader: " + gl.getShaderInfoLog(fsh);
  355. }
  356. var prog = gl.createProgram();
  357. gl.attachShader(prog,vsh);
  358. gl.attachShader(prog, fsh);
  359. if (attribute0) {
  360. gl.bindAttribLocation(prog,0,attribute0);
  361. }
  362. gl.linkProgram(prog);
  363. if ( ! gl.getProgramParameter( prog, gl.LINK_STATUS) ) {
  364. throw "Link error in program: " + gl.getProgramInfoLog(prog);
  365. }
  366. return prog;
  367. }
  368.  
  369.  
  370.  
  371. /* Initialize the WebGL context. Called from init() */
  372. function initGL() {
  373. var prog = createProgram(gl,"vshader-source","fshader-source", "a_coords");
  374. gl.useProgram(prog);
  375. gl.enable(gl.DEPTH_TEST);
  376.  
  377. /* Get attribute and uniform locations */
  378.  
  379. a_coords_loc = gl.getAttribLocation(prog, "a_coords");
  380. a_normal_loc = gl.getAttribLocation(prog, "a_normal");
  381. gl.enableVertexAttribArray(a_coords_loc);
  382. gl.enableVertexAttribArray(a_normal_loc);
  383.  
  384. u_modelview = gl.getUniformLocation(prog, "modelview");
  385. u_projection = gl.getUniformLocation(prog, "projection");
  386. u_normalMatrix = gl.getUniformLocation(prog, "normalMatrix");
  387. u_material = {
  388. diffuseColor: gl.getUniformLocation(prog, "material.diffuseColor"),
  389. specularColor: gl.getUniformLocation(prog, "material.specularColor"),
  390. specularExponent: gl.getUniformLocation(prog, "material.specularExponent")
  391. };
  392. u_lights = new Array(4);
  393. for (var i = 0; i < 4; i++) {
  394. u_lights[i] = {
  395. enabled: gl.getUniformLocation(prog, "lights[" + i + "].enabled"),
  396. position: gl.getUniformLocation(prog, "lights[" + i + "].position"),
  397. color: gl.getUniformLocation(prog, "lights[" + i + "].color")
  398. };
  399. }
  400.  
  401. gl.uniform3f( u_material.diffuseColor, 1, 1, 1 ); // set to white as a default.
  402. gl.uniform3f( u_material.specularColor, 0.9, 0.6, 0.9 ); // specular properties won't change
  403. gl.uniform1f( u_material.specularExponent, 32 );
  404.  
  405. for (var i = 1; i < 4; i++) { // set defaults for lights
  406. gl.uniform1i( u_lights[i].enabled, 0 );
  407. gl.uniform4f( u_lights[i].position, 0, 0, 1, 0 );
  408. gl.uniform3f( u_lights[i].color, 2,1.2,1.4 );
  409. }
  410.  
  411. // Set up lights here; they won't be changed. Lights are fixed in eye coordinates.
  412.  
  413. gl.uniform1i( u_lights[0].enabled, 1 ); // light is a "viewpoint light"
  414. gl.uniform4f( u_lights[0].position, 0,0,0,1 ); // positional, at viewpoint
  415. gl.uniform3f( u_lights[0].color, 0.8, 0.8, 0.8 );
  416.  
  417. gl.uniform1i( u_lights[1].enabled, 1 ); // light 1 is a dimmer light shining from above
  418. gl.uniform4f( u_lights[0].position, 0,1,0,0 ); // diretionsl, from directino of positive y-axis
  419. gl.uniform3f( u_lights[0].color, 0.1, 0.4, 0.4 );
  420.  
  421. gl.uniform1i( u_lights[2].enabled, 0 ); // lightes 2 and 3 are not used.
  422.  
  423. // Note: position and spot direction for lights 1 to 4 are managed by modeling transforms.
  424.  
  425. } // end initGL()
  426.  
  427.  
  428. //---------------------------- rotation by mouse ----------------------------
  429.  
  430. function mouseDown(evt) {
  431. var prevX, prevY;
  432. prevX = evt.clientX;
  433. prevY = evt.clientY;
  434. canvas.addEventListener("mousemove",mouseMove);
  435. document.addEventListener("mouseup",mouseUp);
  436. function mouseMove(evt) {
  437. var dx = evt.clientX - prevX;
  438. var dy = evt.clientY - prevY;
  439. rotateX += dy/200;
  440. rotateY += dx/200;
  441. prevX = evt.clientX;
  442. prevY = evt.clientY;
  443. draw();
  444. }
  445. function mouseUp(evt) {
  446. canvas.removeEventListener("mousemove",mouseMove);
  447. document.removeEventListener("mouseup",mouseUp);
  448. }
  449. }
  450.  
  451.  
  452. //--------------------------------- animation ------------------------------
  453.  
  454. var animating = false;
  455.  
  456. function frame() {
  457. if (animating) {
  458. frameNumber += 1;
  459. draw();
  460.  
  461. requestAnimationFrame(frame);
  462. }
  463. }
  464.  
  465. function setIsAnimating() {
  466. var run = document.getElementById("animCheck").checked;
  467. if (run != animating) {
  468. animating = run;
  469. if (animating)
  470. requestAnimationFrame(frame);
  471. }
  472. }
  473.  
  474. //-------------------------------------------------------------------------
  475.  
  476.  
  477. /**
  478. * initialization function that will be called when the page has loaded
  479. */
  480. function init() {
  481. try {
  482. canvas = document.getElementById("webglcanvas");
  483. gl = canvas.getContext("webgl");
  484. if ( ! gl ) {
  485. throw "Browser does not support WebGL";
  486. }
  487. }
  488. catch (e) {
  489. document.getElementById("message").innerHTML =
  490. "<p>Sorry, could not get a WebGL graphics context.</p>";
  491. return;
  492. }
  493. try {
  494. initGL(); // initialize the WebGL graphics context
  495. }
  496. catch (e) {
  497. document.getElementById("message").innerHTML =
  498. "<p>Sorry, could not initialize the WebGL graphics context:" + e + "</p>";
  499. return;
  500. }
  501. document.getElementById("animCheck").checked = false;
  502. document.getElementById("animCheck").addEventListener("change", setIsAnimating);
  503. document.getElementById("reset").addEventListener("click", function() { rotateX = rotateY = 0; draw(); });
  504. canvas.addEventListener("mousedown", mouseDown);
  505.  
  506. cone = createModel(uvCone()); // create the basic objects
  507. cylinder = createModel(uvCylinder()); // uvCone(), uvCylinder(), and cube()
  508. cube = createModel(cube()); // are defined in basic-object-models-IFS.js
  509. teapot = createModel(teapot());
  510. draw();
  511. }
  512.  
  513.  
  514. </script>
  515. </head>
  516. <body onload="init()">
  517.  
  518. <h2>DiskWorld 2: WebGL Lighting and Hierarchical Modeling</h2>
  519.  
  520.  
  521. <noscript><hr><h3>This page requires Javascript and a web browser that supports WebGL</h3><hr></noscript>
  522.  
  523. <p id="message" style="font-weight:bold">Drag your mouse on the model to rotate it.</p>
  524.  
  525. <p>
  526. <label><input type="checkbox" id="animCheck">Animate</label>
  527. <button id="reset" style="margin-left:40px">Reset</button>
  528. </p>
  529.  
  530.  
  531. <div>
  532.  
  533. <canvas width=800 height=800 id="webglcanvas" style="background-color:blue"></canvas>
  534.  
  535. </div>
  536. </body>
  537. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement