前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CG实验6 交互与动画

CG实验6 交互与动画

作者头像
步行者08
发布2018-10-09 18:07:54
5910
发布2018-10-09 18:07:54
举报
文章被收录于专栏:图形学与OpenGL图形学与OpenGL

1.实验目的和要求

  • 目的:了解交互与动画的基本思想,掌握交互与动画的常见实现方法;
  • 要求:读懂WebGL交互与动画示范代码,实现简单的交互与动画程序。

2. 实验过程

(1) 示范代码1为交互实例:在鼠标点击的位置上绘制出点;示范代码2为动画实例:三角形按照恒定的速度(45度/秒)旋转。结合示范代码,学习理解交互与动画的基本思想与实现; (2) 结合示范代码1,将示范代码2改为根据鼠标来控制三角形的旋转;

3.实验结果

示范代码1的结果如下图所示:

TranslatedTriangle
TranslatedTriangle

示范代码2如下图所示:

Note
Note

4.实验分析

请根据教材内容、网络资源及示范代码,简单分析下交互与动画的实现原理与方法。

5.实验代码

gl-matrix.js 下载地址:http://oty0nwcbq.bkt.clouddn.com/gl-matrix.js

(1) 鼠标点击交互绘点
(i) ClickedPoints.html
代码语言:javascript
复制
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Draw a point with a mouse click</title>
    </head>
    <script id="vertex-shader" type="x-shader/x-vertex">
         attribute vec4 a_Position;  
         void main() { 
           gl_Position = a_Position ; 
           gl_PointSize = 10.0; 
         } 
        </script>

        <script id="fragment-shader" type="x-shader/x-fragment">
             void main() { 
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
             } 
        </script>
    <body onload="startup()">
        <canvas id="myGLCanvas" width="600" height="600">
        </canvas>
    </body>
        <script type="text/javascript" src="gl-matrix.js"></script>
    <script type="text/javascript" src="ClickedPoints.js"></script>
</html>
(ii) ClickedPoints.js
代码语言:javascript
复制
var gl;
function startup(){
    var canvas = document.getElementById('myGLCanvas');//获取<canvas>元素
    gl = createGLContext(canvas);
    setupShaders(); 

 // // Get the storage location of a_Position
 var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
 if (a_Position < 0) {
   console.log('Failed to get the storage location of a_Position');
   return;
 }

 // Register function (event handler) to be called on a mouse press
 canvas.onmousedown = function(ev){ click(ev, gl, canvas, a_Position); };

 // Specify the color for clearing <canvas>
 gl.clearColor(0.0, 0.0, 0.0, 1.0);

 // Clear <canvas>
 gl.clear(gl.COLOR_BUFFER_BIT);
 }

 var g_points = []; // The array for the position of a mouse press
 function click(ev, gl, canvas, a_Position) {
   var x = ev.clientX; // x coordinate of a mouse pointer
   var y = ev.clientY; // y coordinate of a mouse pointer
   var rect = ev.target.getBoundingClientRect() ;

   x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);
   y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);
   // Store the coordinates to g_points array
   g_points.push(x); g_points.push(y);

   // Clear <canvas>
   gl.clear(gl.COLOR_BUFFER_BIT);

   var len = g_points.length;
   for(var i = 0; i < len; i += 2) {
     // Pass the position of a point to a_Position variable
     gl.vertexAttrib3f(a_Position, g_points[i], g_points[i+1], 0.0);

     // Draw
     gl.drawArrays(gl.POINTS, 0, 1);
   }
 }

function createGLContext(canvas) {
  var names = ["webgl", "experimental-webgl"];
  var context = null;
  for (var i=0; i < names.length; i++) {
    try {
      context = canvas.getContext(names[i]); //获取webgl context绘图上下文
    } catch(e) {}
    if (context) {
      break;
    }
  }
  if (context) {
    context.viewportWidth = canvas.width;
    context.viewportHeight = canvas.height;
  } else {
    alert("Failed to create WebGL context!");
  }
  return context;
}

function setupShaders() {    
  var vertexShader = loadShader(gl.VERTEX_SHADER, "vertex-shader");
  var fragmentShader = loadShader(gl.FRAGMENT_SHADER, "fragment-shader");

  var shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.attachShader(shaderProgram, fragmentShader);
  gl.linkProgram(shaderProgram);

  if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
    alert("Failed to setup shaders");
  }

  gl.useProgram(shaderProgram);
  gl.program= shaderProgram;
}

function loadShader(type, ShaderId) {
  var shaderScript = document.getElementById( ShaderId );
    var shader = gl.createShader(type);
    gl.shaderSource( shader, shaderScript.text );
    gl.compileShader( shader );

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert("Error compiling shader" + gl.getShaderInfoLog(shader));
      gl.deleteShader(shader);   
      return null;
  }
  return shader;  
}
(2) 三角形旋转动画
(i) RotatingTriangle.html
代码语言:javascript
复制
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Continually Rotate A Triangle</title>
    </head>
    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 a_Position;
        uniform mat4 u_ModelMatrix;  
        void main() { 
            gl_Position = u_ModelMatrix * a_Position; 
        } 
       </script>

       <script id="fragment-shader" type="x-shader/x-fragment">
            void main() { 
               gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
            } 
       </script>
    <body onload="startup()">
        <canvas id="myGLCanvas" width="600" height="600">
        </canvas>
    </body>
    <script type="text/javascript" src="gl-matrix.js"></script>
    <script type="text/javascript" src="RotatingTriangle.js">
    </script>
</html>
(ii) RotatingTriangle.js
代码语言:javascript
复制
var gl;
// Rotation angle (degrees/second)
var ANGLE_STEP = 45.0;
var modelMatrixI = mat4.create();
function startup(){
    var canvas = document.getElementById('myGLCanvas');//获取<canvas>元素
    gl = createGLContext(canvas);
    setupShaders(); 

  // Write the positions of vertices to a vertex shader
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }

  // Specify the color for clearing <canvas>
  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // Get storage location of u_ModelMatrix
  var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
  if (!u_ModelMatrix) { 
    console.log('Failed to get the storage location of u_ModelMatrix');
    return;
  }

  // Current rotation angle
  var currentAngle = 0.0;
  // Model matrix
  var modelMatrix = mat4.create();

  // Start drawing
  var tick = function() {
    currentAngle = animate(currentAngle);  // Update the rotation angle
    draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
    requestAnimationFrame(tick, canvas); // Request that the browser calls tick
  };
  tick();
 }

 function initVertexBuffers(gl) {
    var vertices = new Float32Array ([
      0, 0.5,   -0.5, -0.5,   0.5, -0.5
    ]);
    var n = 3;   // The number of vertices

    // Create a buffer object
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
      console.log('Failed to create the buffer object');
      return -1;
    }

    // Bind the buffer object to target
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    // Write date into the buffer object
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    // Assign the buffer object to a_Position variable
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if(a_Position < 0) {
      console.log('Failed to get the storage location of a_Position');
      return -1;
    }
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

    // Enable the assignment to a_Position variable
    gl.enableVertexAttribArray(a_Position);

    return n;
  }

  function draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {
    // Set the rotation matrix
    //modelMatrix.setRotate(currentAngle, 0, 0, 1); // Rotation angle, rotation axis (0, 0, 1)
    var radian = Math.PI * currentAngle / 180.0; // Convert to radians
    mat4.rotate(modelMatrix, modelMatrixI, radian, [0, 0 , 1]);

    // Pass the rotation matrix to the vertex shader
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);

    // Clear <canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Draw the rectangle
    gl.drawArrays(gl.TRIANGLES, 0, n);
  }

  // Last time that this function was called
  var g_last = Date.now();
  function animate(angle) {
    // Calculate the elapsed time
    var now = Date.now();
    var elapsed = now - g_last;
    g_last = now;
    // Update the current rotation angle (adjusted by the elapsed time)
    var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
    return newAngle %= 360;
  }

function createGLContext(canvas) {
  var names = ["webgl", "experimental-webgl"];
  var context = null;
  for (var i=0; i < names.length; i++) {
    try {
      context = canvas.getContext(names[i]); //获取webgl context绘图上下文
    } catch(e) {}
    if (context) {
      break;
    }
  }
  if (context) {
    context.viewportWidth = canvas.width;
    context.viewportHeight = canvas.height;
  } else {
    alert("Failed to create WebGL context!");
  }
  return context;
}

function setupShaders() {    
    var vertexShader = loadShader(gl.VERTEX_SHADER, "vertex-shader");
    var fragmentShader = loadShader(gl.FRAGMENT_SHADER, "fragment-shader");

    var shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
      alert("Failed to setup shaders");
    }

    gl.useProgram(shaderProgram);
    gl.program= shaderProgram;
  }

  function loadShader(type, ShaderId) {
    var shaderScript = document.getElementById( ShaderId );
      var shader = gl.createShader(type);
      gl.shaderSource( shader, shaderScript.text );
      gl.compileShader( shader );

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert("Error compiling shader" + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);   
        return null;
    }
    return shader;  
  }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年11月03日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.实验目的和要求
  • 2. 实验过程
  • 3.实验结果
  • 4.实验分析
  • 5.实验代码
    • (1) 鼠标点击交互绘点
      • (i) ClickedPoints.html
    • (ii) ClickedPoints.js
      • (2) 三角形旋转动画
        • (i) RotatingTriangle.html
      • (ii) RotatingTriangle.js
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档