[IG]交互图像-创建3D物体并可旋转、缩放,添加光源照明,凹凸纹理


HTML和JS代码已经贴出,其依赖代码文件Common以及相关资料均请在此处下载

或者请移步我的CSDN仓库

先赞后看,养成习惯!


任务一

给目标增加顶点(20-30个之间),创建一个更复杂的图形

  • 1、在 vertics 中,增加点的坐标
vec4( x, y, z, 1.0 )
  • 2、在colorCube函数中将四个点连成一个面

  • 3、修改numPositions

在这里插入图片描述

任务二

计算重心,并可以绕重心和三个轴旋转

我的策略是,我的图形默认是质量分布均匀的,那么重心就是所有坐标的平均值,计算出来是 ( 0 , 0 , 3 28 ) (0, 0, \frac{3}{28}) (00283),然后我把所有坐标减去这个平均值,就相当于把整个物体往下挪了 3 28 \frac{3}{28} 283,这样重心就和坐标原点重合了,就很容易实现绕重心和三个轴旋转

绕重心旋转我是加个一个用鼠标控制其任意旋转的代码

在这里插入图片描述

任务三

添加一个 viewer position,一个perspective projection,然后计算ModelView and Projection matrices,要求初始时物体要在viewing volume里面,并加按钮或滑块可以随意控制它和viewer position

主要就是ModelView matrix使用 l o o k A t ( e y e , a t u p ) lookAt(eye, at up) lookAt(eye,atup)函数实现,其中 e y e eye eye又由 radius,theta,phi控制

然后Projection matrices由 p e r s p e c t i v e ( f o v y , c a n v a s . w i d t h / c a n v a s . h e i g h t , n e a r , f a r ) perspective(fovy, canvas.width/canvas.height, near, far) perspective(fovy,canvas.width/canvas.height,near,far)控制

最后用控件控制这几个变量就可以了~

在这里插入图片描述
在这里插入图片描述

任务四

添加一个用三角形近似的圆柱体来模拟霓虹灯,放三个光源在里面,并加个开关

使用cylinder函数绘制出圆柱体,把其vertices,normals,TextureCoordinates和原来的图形concat起来。

然后加三个光源,将light position坐标放在圆柱的内部。。,关灯时直接设置 f C o l o r = v e c 4 ( 0 , 0 , 0 , 0 ) fColor=vec4(0, 0, 0, 0) fColor=vec4(0,0,0,0)黑色即可

在这里插入图片描述
在这里插入图片描述

任务五

分配材料属性

这个就简单的修改下 m a t e r i a l A m b i e n t , m a t e r i a l D i f f u s e , m a t e r i a l S p e c u l a r materialAmbient, materialDiffuse, materialSpecular materialAmbient,materialDiffuse,materialSpecular的颜色值就行

在这里插入图片描述

任务六

实现per-vertex和per-fragment shading model,并加个控件来回切换

per-vertex是一开始就实现了的,请看任务五的图片光照

per-fragment这个实现效果如下,他俩差不多的,不过per-fragment显得更真实些,具体请看代码

在这里插入图片描述

任务七

增加凹凸纹理,并设计个按钮来回切换

  • 1、计算出normals,然后用configureTexture绘制纹理

  • 2、在quad函数中给每个vertice添加texture coordinate array

  • 3、传递texCoordsArray到html

  • 4、vertex-shader和fragment-shader中计算 fColor

在这里插入图片描述

HTML 完整实现代码

<!DOCTYPE html>
<html>
<body>
    <div style="text-align:center;">
        <canvas id="gl-canvas" width="512" height="512"></canvas>

        <hr>
        <div>
            <i>Task-2</i>
            <br>
            <button id="ButtonStart">Start</button>
            <button id="ButtonStop">Stop</button>
            <br>
            <button id="ButtonX">Rotate X</button>
            <button id="ButtonY">Rotate Y</button>
            <button id="ButtonZ">Rotate Z</button>
            <br>
            <button id="ButtonRotation">Rotation Around Barycenter Using Mouse</button>
        </div>

        <hr>
        <div>
            <i>Task-3</i>
            <h3 id="info3">Activate Perjection Viewer</h3>
            <button id="SwitchV">Switch</button>
        </div>
        <br>
        <div>
            Radius 1<input id="radius" type="range" min="1" max="6" step="1" value="2" />6
        </div>
        <button id="Button0">Increase Theta</button>
        <button id="Button1">Decrease Theta</button>
        <br>
        <button id="Button2">Increase Phi</button>
        <button id="Button3">Decrease Phi</button>
        <br>
        <button id="Button4">Near</button>
        <button id="Button5">Far</button>
        <div>
            Fovy 1<input id="fovy" type="range" min="1" max="120" step="1" value="100" />120
        </div>

        <hr>
        <div>
            <i>Task-4</i>
            <h3 id="info4">Switch Light</h3>
            NB: Please turn on the light before using other buttons
            <br>
            <button id="SwitchL">Switch</button>
        </div>


        <hr>
        <div>
            <i>Task-6</i>
            <h3 id="info6">Per-Vertex</h3>
            <button id="SwitchP">Switch</button>
        </div>


        <hr>
        <div>
            <i>Task-7</i>
            <h3 id="info7">Activate Bump Texture</h3>
            <button id="SwitchT">Switch</button>
        </div>
    </div>


    <script id="vertex-shader" type="x-shader/x-vertex">
        #version 300 es

        in  vec4 aPosition;
        in  vec3 aNormal;
        out vec4 vColor;

        uniform bool uRotationFlag;
        uniform mat4 uRotationMatrix;

        uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
        uniform vec4 umaterialEmission;
        uniform mat4 uModelViewMatrix;
        uniform mat4 uProjectionMatrix;
        uniform vec4 uLightPosition;
        uniform float uShininess;

        in vec2 aTexCoord;
        out vec2 vTexCoord;
        out vec3 Lt;

        uniform vec4 uNormal;
        uniform bool uTextureFlag;
        uniform vec3 uObjTangent;
        uniform mat3 uNormalMatrix;

        uniform bool uPerFlag;
        out vec3 vN, vL, vE;


        void main()
        {
        if(uPerFlag){
        vec3 pos = -(uModelViewMatrix * aPosition).xyz;

        //fixed light postion

        vec3 light = uLightPosition.xyz;
        vec3 L = normalize(light - pos);
        vec3 E = normalize(-pos);
        vec3 H = normalize(L + E);
        vec4 NN = vec4(aNormal,0);

        // Transform vertex normal into eye coordinates

        vec3 N = normalize((uModelViewMatrix*NN).xyz);

        // Compute terms in the illumination equation
        vec4 ambient = uAmbientProduct;

        float Kd = max(dot(L, N), 0.0);
        vec4  diffuse = Kd*uDiffuseProduct;

        float Ks = pow( max(dot(N, H), 0.0), uShininess );
        vec4  specular = Ks * uSpecularProduct;

        if( dot(L, N) < 0.0 ) {
        specular = vec4(0.0, 0.0, 0.0, 1.0);
        }
        if(uRotationFlag){
        gl_Position = uProjectionMatrix * uModelViewMatrix * uRotationMatrix * aPosition;
        }
        else{
        gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
        }
        vColor = ambient + diffuse +specular;// + umaterialEmission;

        vColor.a = 1.0;
        }

        else{

        vec3 pos = -(uModelViewMatrix * aPosition).xyz;
        vec3 light = uLightPosition.xyz;
        vL = normalize( light - pos );
        vE = -pos;
        vN = normalize( (uModelViewMatrix*vec4(aNormal,0)).xyz);

        if(uRotationFlag){
        gl_Position = uProjectionMatrix * uModelViewMatrix * uRotationMatrix * aPosition;
        }
        else{
        gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
        }

        }


        //Task-7
        if(uTextureFlag){

        vec3 eyePosition = (uModelViewMatrix*aPosition).xyz;
        vec3 eyeLightPos = (uModelViewMatrix*uLightPosition).xyz;

        vec3 N = normalize(uNormalMatrix*uNormal.xyz);
        vec3 T  = normalize(uNormalMatrix*uObjTangent);
        vec3 B = cross(N, T);

        Lt.x = dot(T, eyeLightPos-eyePosition);
        Lt.y = dot(B, eyeLightPos-eyePosition);
        Lt.z = dot(N, eyeLightPos-eyePosition);
        Lt = normalize(Lt);

        vTexCoord = aTexCoord;

        }
        }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
        #version 300 es

        precision mediump float;

        in vec4 vColor;
        out vec4 fColor;

        uniform bool uLightFlag;

        in vec3 Lt;
        uniform bool uTextureFlag;
        in vec2 vTexCoord;
        uniform sampler2D uTexMap;
        uniform vec4 uDiffuseProducttex;


        uniform bool uPerFlag;
        uniform vec4 uAmbientProduct6, uDiffuseProduct6, uSpecularProduct6;
        uniform float uShininess6;
        in vec3 vN, vL, vE;

        void
        main()
        {
        //Task-7

        vec4 N = texture(uTexMap, vTexCoord);
        vec3 NN =  normalize(2.0*N.xyz-1.0);
        vec3 LL = normalize(Lt);
        float Kd7 = max(dot(NN, LL), 0.0);

        if(uPerFlag){

        if(uTextureFlag){
        fColor = vColor * vec4(Kd7*uDiffuseProducttex.xyz, 1.0);}
        else{fColor = vColor;}
        }

        else{

        vec3 H = normalize( vL + vE );
        vec4 ambient = uAmbientProduct6;

        float Kd = max( dot(vL, vN), 0.0 );
        vec4 diffuse = Kd * uDiffuseProduct6;

        float Ks = pow( max(dot(vN, H), 0.0), uShininess6 );
        vec4 specular = Ks * uSpecularProduct6;

        if( dot(vL, vN) < 0.0 ) specular = vec4(0.0, 0.0, 0.0, 1.0);
        if(uTextureFlag){
        fColor = (ambient + diffuse +specular)*vec4(Kd7*uDiffuseProducttex.xyz, 1.0);}
        else{fColor = ambient + diffuse +specular;}
        fColor.a = 1.0;

        }

        if(uLightFlag){
        fColor = vec4( 0.0, 0.0, 0.0, 1.0 );;
        }

        }
    </script>

    <script src="../Common/initShaders.js"></script>
    <script src="../Common/MVnew.js"></script>
    <script src="Homework1.js"></script>


</body>
</html>

JavaScript 完整实现代码

"use strict";

var shadedCube = function() {

var canvas;
var gl;



var positionsArray = [];
var normalsArray = [];


//-----------------------------------------------------------------------------------------------------------------------
//Task-4
var lightPosition = vec4(0.71, 0.77, 0.11, 1.0);

var lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);

var lightAmbient2 = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse2 = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular2 = vec4(1.0, 1.0, 1.0, 1.0);

var lightAmbient3 = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse3 = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular3 = vec4(1.0, 1.0, 1.0, 1.0);
//-----------------------------------------------------------------------------------------------------------------------



//-----------------------------------------------------------------------------------------------------------------------
//Task-5
var materialAmbient = vec4(1.0, 0.3, 0.0, 1.0);
var materialDiffuse = vec4(1.0, 0.8, 0.1, 1.0);
var materialSpecular = vec4(1.0, 0.7, 0.0, 1.0);
var materialEmission = vec4(0.0, 0.3, 0.3, 1.0);  //Task-4

var materialShininess = 80.0;
//-----------------------------------------------------------------------------------------------------------------------




var ctm;
var ambientColor, diffuseColor, specularColor;
var modelViewMatrix, projectionMatrix, nMatrix;
var viewerPos;
var program;

var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var theta = vec3(0, 0, 0);
var thetaLoc;

var flag = false;



//-------------------------------------------------------
// Task-1
var numPositions = 156; 
var vertices = [

    vec4( -0.5, -0.5,  0.5-4*0.75/28, 1.0 ), // 0
    vec4( -0.5,  0.5,  0.5-4*0.75/28, 1.0 ), // 1
    vec4( 0.5,  0.5,  0.5-4*0.75/28, 1.0 ),  // 2
    vec4( 0.5, -0.5,  0.5-4*0.75/28, 1.0 ),  // 3
    vec4( -0.5, -0.5, -0.5-4*0.75/28, 1.0 ), // 4
    vec4( -0.5,  0.5, -0.5-4*0.75/28, 1.0 ), // 5
    vec4( 0.5,  0.5, -0.5-4*0.75/28, 1.0 ),  // 6
    vec4( 0.5, -0.5, -0.5-4*0.75/28, 1.0 ),  // 7
    
    vec4(-0.25, -0.25, 0.75-4*0.75/28, 1.0), // 8
    vec4(-0.25, 0.25, 0.75-4*0.75/28, 1.0),  // 9
    vec4(0.25, 0.25, 0.75-4*0.75/28, 1.0),   // 10
    vec4(0.25, -0.25, 0.75-4*0.75/28, 1.0),  // 11

    vec4(-0.25, 0.75, 0.25-4*0.75/28, 1.0),  // 12
    vec4(0.25, 0.75, 0.25-4*0.75/28, 1.0),   // 13
    vec4(-0.25, 0.75, -0.25-4*0.75/28, 1.0), // 14
    vec4(0.25, 0.75, -0.25-4*0.75/28, 1.0),  // 15

    vec4(-0.25, -0.75, 0.25-4*0.75/28, 1.0), // 16
    vec4(0.25, -0.75, 0.25-4*0.75/28, 1.0),  // 17
    vec4(-0.25, -0.75, -0.25-4*0.75/28, 1.0),// 18
    vec4(0.25, -0.75, -0.25-4*0.75/28, 1.0), // 19

    vec4(-0.75, 0.25, 0.25-4*0.75/28, 1.0),  // 20
    vec4(-0.75, -0.25, 0.25-4*0.75/28, 1.0), // 21
    vec4(-0.75, 0.25, -0.25-4*0.75/28, 1.0), // 22
    vec4(-0.75, -0.25, -0.25-4*0.75/28, 1.0),// 23

    vec4(0.75, 0.25, 0.25-4*0.75/28, 1.0),   // 24
    vec4(0.75, -0.25, 0.25-4*0.75/28, 1.0),  // 25
    vec4(0.75, 0.25, -0.25-4*0.75/28, 1.0),  // 26
    vec4(0.75, -0.25, -0.25-4*0.75/28, 1.0), // 27
    ];
//-------------------------------------------------------



//-----------------------------------------------------------------------------------------------------------------------
//Task-2
var RotationFlag = false;
var rotationMatrix= mat4();
var rotationMatrixLoc;

var  angle = 0.0;
var  axis2 = vec3(0, 0, 1);

var trackingMouse = false;
var trackballMove = false;

var lastPos = [0, 0, 0];
var curx, cury;
var startX, startY;

function trackballView( x,  y ) {
    var d, a;
    var v = [];

    v[0] = x;
    v[1] = y;

    d = v[0]*v[0] + v[1]*v[1];
    if (d < 1.0)
      v[2] = Math.sqrt(1.0 - d);
    else {
      v[2] = 0.0;
      a = 1.0 /  Math.sqrt(d);
      v[0] *= a;
      v[1] *= a;
    }
    return v;
}

function mouseMotion( x,  y)
{
    var dx, dy, dz;

    var curPos = trackballView(x, y);
    if(trackingMouse) {
      dx = curPos[0] - lastPos[0];
      dy = curPos[1] - lastPos[1];
      dz = curPos[2] - lastPos[2];

      if (dx || dy || dz) {
	       angle = -0.1 * Math.sqrt(dx*dx + dy*dy + dz*dz);

	       axis2[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
	       axis2[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
	       axis2[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];

         lastPos[0] = curPos[0];
	       lastPos[1] = curPos[1];
	       lastPos[2] = curPos[2];
      }
    }
    render();
}

function startMotion( x,  y)
{
    trackingMouse = true;
    startX = x;
    startY = y;
    curx = x;
    cury = y;

    lastPos = trackballView(x, y);
	  trackballMove=true;
}

function stopMotion( x,  y)
{
    trackingMouse = false;
    if (startX != x || startY != y) {
    }
    else {
	     angle = 0.0;
	     trackballMove = false;
    }
}
//-----------------------------------------------------------------------------------------------------------------------




//-------------------------------------------------------
//Task-3
var viewerFlag = true; 
var fovy = 100.0;
var near = 0.3;
var far = 3.0;
var radius = 3.0;
var thetav = 0.0;
var phi = 0.0;
const at = vec3(0.0, 0.0, 0.0);
const up = vec3(0.0, 1.0, 0.0);
var dr = 5.0 * Math.PI/180.0;
//-------------------------------------------------------




//----------------------------------------------------------------------------------------------------------------------
//Task-4
var ncylinder;
var lightFlag = false;

function cylinder(numSlices, numStacks, caps) {

    var slices = 36;
    if(numSlices) slices = numSlices;
    var stacks = 1;
    if(numStacks) stacks = numStacks;
    var capsFlag = true;
    if(caps==false) capsFlag = caps;

    var data = {};

    var top = 0.5;
    var bottom = -0.5;
    var radius = 0.5;
    var topCenter = [0.0, top, 0.0];
    var bottomCenter = [0.0, bottom, 0.0];


    var sideColor = [1.0, 0.0, 0.0, 1.0];
    var topColor = [0.0, 1.0, 0.0, 1.0];
    var bottomColor = [0.0, 0.0, 1.0, 1.0];


    var cylinderVertexCoordinates = [];
    var cylinderNormals = [];
    var cylinderVertexColors = [];
    var cylinderTextureCoordinates = [];

    // side

    for(var j=0; j<stacks; j++) {
      var stop = bottom + (j+1)*(top-bottom)/stacks;
      var sbottom = bottom + j*(top-bottom)/stacks;
      var topPoints = [];
      var bottomPoints = [];
      var topST = [];
      var bottomST = [];
      for(var i =0; i<slices; i++) {
        var theta = 2.0*i*Math.PI/slices;
        topPoints.push([radius*Math.sin(theta), stop, radius*Math.cos(theta), 1.0]);
        bottomPoints.push([radius*Math.sin(theta), sbottom, radius*Math.cos(theta), 1.0]);
      };

      topPoints.push([0.0, stop, radius, 1.0]);
      bottomPoints.push([0.0,  sbottom, radius, 1.0]);


      for(var i=0; i<slices; i++) {
        var a = topPoints[i];
        var d = topPoints[i+1];
        var b = bottomPoints[i];
        var c = bottomPoints[i+1];
        var u = [b[0]-a[0], b[1]-a[1], b[2]-a[2]];
        var v = [c[0]-b[0], c[1]-b[1], c[2]-b[2]];

        var normal = [
          u[1]*v[2] - u[2]*v[1],
          u[2]*v[0] - u[0]*v[2],
          u[0]*v[1] - u[1]*v[0]
        ];

        var mag = Math.sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2])
        normal = [normal[0]/mag, normal[1]/mag, normal[2]/mag];
        cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);

        cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([i/slices, (j-1)*(top-bottom)/stacks]);

        cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([(i+1)/slices, (j-1)*(top-bottom)/stacks]);

        cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);

        cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([(i+1)/slices, (j-1)*(top-bottom)/stacks]);

        cylinderVertexCoordinates.push([d[0], d[1], d[2], 1.0]);
        cylinderVertexColors.push(sideColor);
        cylinderNormals.push([normal[0], normal[1], normal[2]]);
        cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);
      };
    };

      var topPoints = [];
      var bottomPoints = [];
      for(var i =0; i<slices; i++) {
        var theta = 2.0*i*Math.PI/slices;
        topPoints.push([radius*Math.sin(theta), top, radius*Math.cos(theta), 1.0]);
        bottomPoints.push([radius*Math.sin(theta), bottom, radius*Math.cos(theta), 1.0]);
      };
      topPoints.push([0.0, top, radius, 1.0]);
      bottomPoints.push([0.0,  bottom, radius, 1.0]);

    if(capsFlag) {

    //top

    for(i=0; i<slices; i++) {
      normal = [0.0, 1.0, 0.0];
      var a = [0.0, top, 0.0, 1.0];
      var b = topPoints[i];
      var c = topPoints[i+1];
      cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
      cylinderVertexColors.push(topColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);

      cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
      cylinderVertexColors.push(topColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);

      cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
      cylinderVertexColors.push(topColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);
    };

    //bottom

    for(i=0; i<slices; i++) {
      normal = [0.0, -1.0, 0.0];
      var a = [0.0, bottom, 0.0, 1.0];
      var b = bottomPoints[i];
      var c = bottomPoints[i+1];
      cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
      cylinderVertexColors.push(bottomColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);

      cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
      cylinderVertexColors.push(bottomColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);

      cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
      cylinderVertexColors.push(bottomColor);
      cylinderNormals.push(normal);
      cylinderTextureCoordinates.push([0, 1]);
    };

    };
    function translate(x, y, z){
       for(var i=0; i<cylinderVertexCoordinates.length; i++) {
         cylinderVertexCoordinates[i][0] += x;
         cylinderVertexCoordinates[i][1] += y;
         cylinderVertexCoordinates[i][2] += z;
       };
    }

    function scale(sx, sy, sz){
        for(var i=0; i<cylinderVertexCoordinates.length; i++) {
            cylinderVertexCoordinates[i][0] *= sx;
            cylinderVertexCoordinates[i][1] *= sy;
            cylinderVertexCoordinates[i][2] *= sz;
            cylinderNormals[i][0] /= sx;
            cylinderNormals[i][1] /= sy;
            cylinderNormals[i][2] /= sz;
        };
    }

    function radians( degrees ) {
        return degrees * Math.PI / 180.0;
    }

    function rotate( angle, axis) {

        var d = Math.sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);

        var x = axis[0]/d;
        var y = axis[1]/d;
        var z = axis[2]/d;

        var c = Math.cos( radians(angle) );
        var omc = 1.0 - c;
        var s = Math.sin( radians(angle) );

        var mat = [
            [ x*x*omc + c,   x*y*omc - z*s, x*z*omc + y*s ],
            [ x*y*omc + z*s, y*y*omc + c,   y*z*omc - x*s ],
            [ x*z*omc - y*s, y*z*omc + x*s, z*z*omc + c ]
        ];

        for(var i=0; i<cylinderVertexCoordinates.length; i++) {
              var u = [0, 0, 0];
              var v = [0, 0, 0];
              for( var j =0; j<3; j++)
               for( var k =0 ; k<3; k++) {
                  u[j] += mat[j][k]*cylinderVertexCoordinates[i][k];
                  v[j] += mat[j][k]*cylinderNormals[i][k];
                };
               for( var j =0; j<3; j++) {
                 cylinderVertexCoordinates[i][j] = u[j];
                 cylinderNormals[i][j] = v[j];
               };
        };
    }

    data.TriangleVertices = cylinderVertexCoordinates;
    data.TriangleNormals = cylinderNormals;
    data.TriangleVertexColors = cylinderVertexColors;
    data.TextureCoordinates = cylinderTextureCoordinates;
    data.rotate = rotate;
    data.translate = translate;
    data.scale = scale;
    return data;
}
//----------------------------------------------------------------------------------------------------------------------


//-------------------------------------------------------
//Task-6
var perFlag = true; 
//-------------------------------------------------------





//-------------------------------------------------------
//Task-7
var texSize = 256/2;
var texCoordsArray = [];

var data = new Array()
    for (var i = 0; i<= texSize; i++)  data[i] = new Array();
    for (var i = 0; i<= texSize; i++) for (var j=0; j<=texSize; j++)
        data[i][j] = 0.0;
    for (var i = texSize/4; i<3*texSize/4; i++) for (var j = texSize/4; j<3*texSize/4; j++)
        data[i][j] = 1.0;

var normalst = new Array()
    for (var i=0; i<texSize; i++)  normalst[i] = new Array();
    for (var i=0; i<texSize; i++) for ( var j = 0; j < texSize; j++)
        normalst[i][j] = new Array();
    for (var i=0; i<texSize; i++) for ( var j = 0; j < texSize; j++) {
        normalst[i][j][0] = data[i][j]-data[i+1][j];
        normalst[i][j][1] = data[i][j]-data[i][j+1];
        normalst[i][j][2] = 1;
    }

    for (var i=0; i<texSize; i++) for (var j=0; j<texSize; j++) {
       var d = 0;
       for(k=0;k<3;k++) d+=normalst[i][j][k]*normalst[i][j][k];
       d = Math.sqrt(d);
       for(k=0;k<3;k++) normalst[i][j][k]= 0.5*normalst[i][j][k]/d + 0.5;
    }

var normals = new Uint8Array(3*texSize*texSize);

    for ( var i = 0; i < texSize; i++ )
        for ( var j = 0; j < texSize; j++ )
           for(var k =0; k<3; k++)
                normals[3*texSize*i+3*j+k] = 255*normalst[i][j][k];

var texCoord = [
    vec2(0, 0),
    vec2(0, 1),
    vec2(1, 1),
    vec2(1, 0)
];

function configureTexture( image ) {
    var texture = gl.createTexture();
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, texSize, texSize, 0, gl.RGB, gl.UNSIGNED_BYTE, image);
    gl.generateMipmap(gl.TEXTURE_2D);
}

var textureFlag = false;                //Task-7
var normal = vec4(0.0, 1.0, 0.0, 0.0); //Task-7
var tangent = vec3(1.0, 0.0, 0.0);     //Task-7
//-------------------------------------------------------

init();

function quad(a, b, c, d) {

     var t1 = subtract(vertices[b], vertices[a]);
     var t2 = subtract(vertices[c], vertices[b]);
     var normal = cross(t1, t2);
     normal = vec3(normal);


     positionsArray.push(vertices[a]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[0]);

     positionsArray.push(vertices[b]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[1]);

     positionsArray.push(vertices[c]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[2]);

     positionsArray.push(vertices[a]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[0]);

     positionsArray.push(vertices[c]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[2]);

     positionsArray.push(vertices[d]);
     normalsArray.push(normal);
     texCoordsArray.push(texCoord[3]);
}


function colorCube()
{
//-------------------------------------------------------
// Task-1
    quad( 8, 9, 10, 11 );
    quad( 0, 1, 9, 8 );
    quad( 9, 10, 2, 1 );
    quad( 10, 11, 3, 2 );
    quad( 11, 8, 0, 3);

    quad( 14, 12, 13, 15 );
    quad( 1, 12, 14, 5 );
    quad( 1, 12, 13, 2 );
    quad( 2, 13, 15, 6 );
    quad( 5, 14, 15, 6 );

    quad( 16, 17, 19, 18 );
    quad( 0, 16, 18, 4 );
    quad( 0, 16, 17, 3 );
    quad( 3, 17, 19, 7 );
    quad( 4, 18, 19, 7 );

    quad( 20, 21, 23, 22 );
    quad( 1, 20, 22, 5 );
    quad( 1, 20, 21, 0 );
    quad( 0, 21, 23, 4 );
    quad( 5, 22, 23, 4 );

    quad( 24, 25, 27, 26 );
    quad( 2, 24, 25, 3 );
    quad( 2, 24, 26, 6 );
    quad( 3, 25, 27, 7 );
    quad( 6, 26, 27, 7 );

    quad( 4, 5, 6, 7 );
}
//-------------------------------------------------------


function init() {
    canvas = document.getElementById("gl-canvas");

    gl = canvas.getContext('webgl2');
    if (!gl) alert( "WebGL 2.0 isn't available");


    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(1.0, 1.0, 1.0, 1.0);

    gl.enable(gl.DEPTH_TEST);

//-------------------------------------------------------------------------------------
//Task-4
    var myCylinder = cylinder(8, 1, true);
    myCylinder.scale(0.2, 0.2, 0.2);
    myCylinder.rotate(-45.0, [ 1, 1, 1]);
    myCylinder.translate(0.8, 0.8, 0.0);

    var points2 = myCylinder.TriangleVertices;
    var normals2 = myCylinder.TriangleNormals;
    var texCoord2 = myCylinder.TextureCoordinates;

    ncylinder = myCylinder.TriangleVertices.length;

    positionsArray = positionsArray.concat(points2);
    normalsArray = normalsArray.concat(normals2);
    texCoordsArray = texCoordsArray.concat(texCoord2);
//---------------------------------------------------------------------------------------


    //
    //  Load shaders and initialize attribute buffers
    //
    program = initShaders(gl, "vertex-shader", "fragment-shader");
    gl.useProgram(program);

    colorCube();

    var nBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);

    var normalLoc = gl.getAttribLocation(program, "aNormal");
    gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalLoc);

    var vBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);

    var positionLoc = gl.getAttribLocation(program, "aPosition");
    gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionLoc);

    thetaLoc = gl.getUniformLocation(program, "theta");

    

//--------------------------------------------------------------------------------------
//Task-7    
    var tBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, tBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, flatten(texCoordsArray), gl.STATIC_DRAW);
    
    var texCoordLoc = gl.getAttribLocation(program, "aTexCoord");
    gl.vertexAttribPointer(texCoordLoc, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(texCoordLoc);
    
    configureTexture(normals); 
//-----------------------------------------------------------------------------------------





    var ambientProduct = mult(lightAmbient, materialAmbient);
    var diffuseProduct = mult(lightDiffuse, materialDiffuse);
    var specularProduct = mult(lightSpecular, materialSpecular);

//-----------------------------------------------------------------------------------------
    var ambientProduct2 = mult(lightAmbient2, materialAmbient);
    var diffuseProduct2 = mult(lightDiffuse2, materialDiffuse);
    var specularProduct2 = mult(lightSpecular2, materialSpecular);

    var ambientProduct3 = mult(lightAmbient3, materialAmbient);
    var diffuseProduct3 = mult(lightDiffuse3, materialDiffuse);
    var specularProduct3 = mult(lightSpecular3, materialSpecular);
//-----------------------------------------------------------------------------------------




    document.getElementById("ButtonX").onclick = function(){axis = xAxis;};
    document.getElementById("ButtonY").onclick = function(){axis = yAxis;};
    document.getElementById("ButtonZ").onclick = function(){axis = zAxis;};
    document.getElementById("ButtonRotation").onclick = function(){RotationFlag = !RotationFlag;}; //Task-2
    document.getElementById("ButtonStart").onclick = function(){flag = true;}; //Task-2
    document.getElementById("ButtonStop").onclick = function(){flag = false;}; //Task-2
    document.getElementById("SwitchL").onclick = function(event){
        lightFlag =! lightFlag;
        if(lightFlag){
            document.getElementById('info4').innerHTML = "Turn On";
        }
        else{
            document.getElementById('info4').innerHTML = "Turn Off";
        }
    }; //Task-4
    document.getElementById("SwitchP").onclick = function(event){
        perFlag =! perFlag;
        if(perFlag){
            document.getElementById('info6').innerHTML = "Per-Vertex";
        }
        else{
            document.getElementById('info6').innerHTML = "Per-Fragment";
        }
    }; //Task-6
    document.getElementById("SwitchT").onclick = function(event){
        textureFlag =! textureFlag;
        if(textureFlag){
            document.getElementById('info7').innerHTML = "Deactivate Bump Texture";
        }
        else{
            document.getElementById('info7').innerHTML = "Activate Bump Texture";
        }
    }; //Task-7


//-----------------------------------------------------------------------------------------------------------------------
//Task-3
    document.getElementById("SwitchV").onclick = function(event){
        viewerFlag =! viewerFlag;
        if(viewerFlag){
            document.getElementById('info3').innerHTML = "Activate Perjection Viewer";
        }
        else{
            document.getElementById('info3').innerHTML = "Deactivate Perjection Viewer";
        }
    }; 
    document.getElementById("radius").onchange = function(event) {radius = event.target.value/2;};

    document.getElementById("Button0").onclick = function(){thetav += dr;};
    document.getElementById("Button1").onclick = function(){thetav -= dr;};
    document.getElementById("Button2").onclick = function(){phi += dr;};
    document.getElementById("Button3").onclick = function(){phi -= dr;};
    document.getElementById("Button4").onclick = function(){near  *= 1.1; far *= 1.1;};
    document.getElementById("Button5").onclick = function(){near  *= 0.9; far *= 0.9;};
    document.getElementById("fovy").onchange = function(event) {fovy = event.target.value;};
//---------------------------------------------------------------------------------------------------------------------



    
//---------------------------------------------------------------------------------------------------------------------
//Task-4
    var av = vec4(1/3, 1/3, 1/3, 1/3);
    gl.uniform4fv(gl.getUniformLocation(program, "uAmbientProduct"), mult(add(add(ambientProduct,ambientProduct2),ambientProduct3), av));
    gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProduct"), mult(add(add(diffuseProduct,diffuseProduct2),diffuseProduct3),av));
    gl.uniform4fv(gl.getUniformLocation(program, "uSpecularProduct"),mult(add(add(specularProduct,specularProduct2),specularProduct3),av));
    gl.uniform4fv(gl.getUniformLocation(program, "umaterialEmission"), materialEmission );//Task-4

//---------------------------------------------------------------------------------------------------------------------


    gl.uniform4fv(gl.getUniformLocation(program, "uLightPosition"), lightPosition );
    gl.uniform1f(gl.getUniformLocation(program, "uShininess"), materialShininess);


//------------------------------------------------------------------------------------------------------------------------
//Task-2
    rotationMatrix = mat4();
    rotationMatrixLoc = gl.getUniformLocation(program, "uRotationMatrix");
    gl.uniformMatrix4fv(rotationMatrixLoc, false, flatten(rotationMatrix));

    canvas.addEventListener("mousedown", function(event){
        var x = 2*event.clientX/canvas.width-1;
        var y = 2*(canvas.height-event.clientY)/canvas.height-1;
        startMotion(x, y);
    });

    canvas.addEventListener("mouseup", function(event){
        var x = 2*event.clientX/canvas.width-1;
        var y = 2*(canvas.height-event.clientY)/canvas.height-1;
        stopMotion(x, y);
    });

    canvas.addEventListener("mousemove", function(event){

        var x = 2*event.clientX/canvas.width-1;
        var y = 2*(canvas.height-event.clientY)/canvas.height-1;
        mouseMotion(x, y);
    } );
//------------------------------------------------------------------------------------------------------------------------




//------------------------------------------------------------------------------------------------------------------------
//Task-6
    gl.uniform4fv(gl.getUniformLocation(program, "uAmbientProduct6"), ambientProduct);
    gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProduct6"), diffuseProduct );
    gl.uniform4fv(gl.getUniformLocation(program, "uSpecularProduct6"), specularProduct );
    gl.uniform1f(gl.getUniformLocation(program, "uShininess6"), materialShininess);
//------------------------------------------------------------------------------------------------------------------------




//------------------------------------------------------------------------------------------------------------------------
//Task-7
    gl.uniform4fv( gl.getUniformLocation(program, "uNormal"), normal);           
    gl.uniform3fv( gl.getUniformLocation(program, "uObjTangent"), tangent);      
    gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProducttex"), diffuseProduct );
//------------------------------------------------------------------------------------------------------------------------


    render();
}

function render(){
    
    gl.useProgram(program);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    if (viewerFlag){

        if(flag) theta[axis] += 2.0;

        modelViewMatrix = mat4();
        modelViewMatrix = mult(modelViewMatrix, rotate(theta[xAxis], vec3(1, 0, 0)));
        modelViewMatrix = mult(modelViewMatrix, rotate(theta[yAxis], vec3(0, 1, 0)));
        modelViewMatrix = mult(modelViewMatrix, rotate(theta[zAxis], vec3(0, 0, 1)));
        
        nMatrix = normalMatrix(modelViewMatrix, true); //Task-7
    
        projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);
    }

//------------------------------------------------------------------------------------------------------------------------
//Task-3
    else{    
        var eye = vec3(radius*Math.sin(thetav)*Math.cos(phi),
                    radius*Math.sin(thetav)*Math.sin(phi),
                    radius*Math.cos(thetav));
        var modelViewMatrix = lookAt(eye, at, up);

        projectionMatrix = perspective(fovy, canvas.width/canvas.height,  near, far);
    }
//------------------------------------------------------------------------------------------------------------------------
   
    lightPosition[0] = lightPosition[0] + radius*Math.sin(thetav)*Math.cos(phi);
    lightPosition[1] = lightPosition[1] + radius*Math.sin(thetav)*Math.sin(phi);
    lightPosition[2] = lightPosition[2] + radius*Math.cos(thetav);
    
    if(RotationFlag){
        if(trackballMove) {
            axis2 = normalize(axis2);
            rotationMatrix = mult(rotationMatrix, rotate(angle, axis2));
            gl.uniformMatrix4fv(rotationMatrixLoc, false, flatten(rotationMatrix));
        }
        gl.uniform1f(gl.getUniformLocation(program, "uRotationFlag"), RotationFlag);//Task-2
    }
    
    gl.uniformMatrix4fv(gl.getUniformLocation(program, "uModelViewMatrix"), false, flatten(modelViewMatrix));


    gl.uniformMatrix4fv( gl.getUniformLocation(program, "uProjectionMatrix"), false, flatten(projectionMatrix)); //Task-3
    gl.uniform1i( gl.getUniformLocation(program, "uLightFlag"), lightFlag); //Task-4
    gl.uniform1i( gl.getUniformLocation(program, "uPerFlag"), perFlag); //Task-6
    gl.uniformMatrix3fv( gl.getUniformLocation(program, "uNormalMatrix"), false, flatten(nMatrix));  //Task-7
    gl.uniform1i( gl.getUniformLocation(program, "uTextureFlag"), textureFlag); //Task-7
    
//------------------------------------------------------------------------------------------------------------------------
//Task-4
    gl.drawArrays(gl.TRIANGLES, 0, numPositions+ncylinder);
//------------------------------------------------------------------------------------------------------------------------
      

    requestAnimationFrame(render);
}

}

shadedCube();
```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是土豆大叔啊!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值