Bootstrap

计算机图形学——实验三光照与材质处理实验

实验内容

        1.对实验二绘制的正三棱锥增加光照,实现点光源的光照效果,分别在顶点着色器和片元着色器中实现,观察有什么区别。把点光源改成平行光,观察有什么变化。

        2.使点光源围绕三棱锥旋转,呈现在不同位置照射三棱锥的效果。

实验设计思路

         光照处理:采用Blinn-Phong反射模型,在着色器中计算三种光的光强,将三种光相加并与物体的原色相乘得到最终的着色。

         环境光反射光强Ia由表面的环境光反射系数ka确定

                        ​​​​​​​        ​​​​​​​        ​​​​​​​     

        漫反射光的颜色Id取决于入射光光强Ld、材质反射系数kd、入射光与表面形成的入射角θ

                                                

                                            

        增加距离衰减因子后为

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

       镜面反射光的颜色Is取决于入射光光强Ls、材质反射系数ks、半角向量h与法向量n的夹角ψ、高光指数a

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​     

        增加距离衰减因子后为

                                        

        因此最终计算出的光强为

                         

        本实验中不考虑距离衰减因子

        在着色器中比实验三的程序多了①相机位置②光源位置③光色(默认白色即1.0,1.0,1.0)④法线变换矩阵

        根据Blinn-Phong模型的图示

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

        归一化:向一个向量转化为对应方向的单位向量

        入射光方向I =  归一化(光源位置 - 着色点位置)

        视线方向 v= 归一化(相机位置 - 着色点位置)

        半程向量h = 归一化(入射光方向+视线方向)        

        最后利用这些数据代入公式即可算出最终反射的光强。

        

        在顶点着色器中实现光照操作,只计算了几个点的最终颜色值,最后的结果会进行插值操作,导致结果不真实

        在片段着色器中实现光照操作,对每个像素都计算的其颜色值,最终的结果会更加真实。

        平行光源的实现:将上述点光源的着色器中的光照方向改为一个固定的值即可。

        光源的旋转操作:为光源额外设置一个旋转矩阵,并传入着色器与光源位置相乘即可得到变化后的光源位置。

实验结果

点光源+旋转(顶点着色器实现)

点光源+旋转(片段着色器实现)

平行光源(片段着色器实现)

实验代码

        点光源+旋转(顶点着色器)

 // 获取WebGL上下文  
    const canvas = document.getElementById('webglCanvas');
    const gl = canvas.getContext('webgl');

    // 初始化着色器  
    const vertexShaderSource = `  
    attribute vec3 position; 
    attribute vec3 normal;
    attribute vec3 color;

    uniform mat4 modelMatrix;
    uniform mat4 visionMatrix;
    uniform mat4 perspectiveMatrix;
    uniform mat4 lightTransformMatrix;
    uniform mat4 normalMatrix;

    uniform vec3 cameraPosition;
    uniform vec3 lightColor;
    uniform vec3 lightPosition;

    varying vec3 vColor; 
    varying vec3 vNormal;

    void main() {  
        gl_Position =perspectiveMatrix* visionMatrix * modelMatrix * vec4(position, 1.0); 
        vec3 transformedPoint = (modelMatrix * vec4(position, 1.0)).xyz;
        vNormal = normalize((normalMatrix * vec4(normal,1.0)).xyz);
        vec3 transLight = (lightTransformMatrix * vec4(lightPosition, 1.0)).xyz;
        vec3 lightVec = normalize(transLight-transformedPoint);
        vec3 cameraVec = normalize(cameraPosition-transformedPoint);
        vec3 halfVec = normalize(lightVec+cameraVec);
        float lightCos = max(dot(lightVec,normal),0.0);
        float lightCosHalf = max(dot(lightVec,halfVec),0.0);

        vec3 ambientLight = lightColor*0.3;
        vec3 diffuseLight = lightColor*lightCos*1.0;
        vec3 specularLight = lightColor*pow(lightCosHalf,20.0)*0.5;


        vColor =(ambientLight + specularLight + diffuseLight)*color; 
    }  
`;

    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);

    const fragmentShaderSource = `  
    precision mediump float; 
    varying vec3 vNormal; 
    varying vec3 vColor;
    void main() {  
        gl_FragColor = vec4(vColor ,1.0); 
    }  
`;

    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);

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

    //初始化数据
    var transformMatrix = glMatrix.mat4.create();
    var t1, t2, t3 = null

    const vertices = new Float32Array([
      0, 0, -1,
      0, 0.942809, 0.333333,
      -0.816497, -0.471405, 0.333333,
      0.816497, -0.471405, 0.333333,

    ]);

    const indices = new Uint16Array([
      1, 2, 3,
      1, 2, 0,
      1, 3, 0,
      2, 3, 0,

    ]);

    const colors = new Float32Array([
      1, 0, 0,
      0, 1, 0,
      0, 0, 1,
      1, 1, 0,
    ])

    const normal = new Float32Array(
      [
        0, 0, -1,
        0, 0.942809, 0.333333,
        -0.816496, -0.471404, 0.333333,
        0.816496, -0.471404, 0.333333,
      ]
    )

    // 传入数据
    const vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'position');
    gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionAttributeLocation);

    const indicesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

    const colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

    const colorAttributeLocation = gl.getAttribLocation(shaderProgram, 'color');
    gl.vertexAttribPointer(colorAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(colorAttributeLocation);

    const normalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, normal, gl.STATIC_DRAW);

    const normalAttributeLocation = gl.getAttribLocation(shaderProgram, 'normal');
    gl.vertexAttribPointer(normalAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalAttributeLocation);

    //传入相机位置数据
    const cameraPoint = glMatrix.vec3.fromValues(2.0, 2.0, 3.0);
    const cameraPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'cameraPosition');
    gl.uniform3fv(cameraPositionVecUniformLocation, cameraPoint);

    //传入光源颜色数据
    const lightColor = glMatrix.vec3.fromValues(1.0, 1.0, 1.0);
    const lightColorVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightColor');
    gl.uniform3fv(lightColorVecUniformLocation, lightColor);

    //传入光源位置数据
    const lightPosition = glMatrix.vec3.fromValues(0.0, 5.0, 0.0);
    const lightPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightPosition');
    gl.uniform3fv(lightPositionVecUniformLocation, lightPosition);

    //传入模型变换矩阵
    const modelMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'modelMatrix');
    var modelMatrix = glMatrix.mat4.create();
    gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);

    //传入视图变换矩阵
    const visionMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'visionMatrix');
    const eye = cameraPoint;
    const look = glMatrix.vec3.fromValues(0, 0, 0);
    const up = glMatrix.vec3.fromValues(0, 1, 0);
    const visionMatrix = glMatrix.mat4.lookAt(glMatrix.mat4.create(), eye, look, up);
    gl.uniformMatrix4fv(visionMatrixUniformLocation, false, visionMatrix);

    //传入透视矩阵
    const perspectiveMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'perspectiveMatrix');
    const perspectiveMatrix = glMatrix.mat4.perspective(glMatrix.mat4.create(), Math.PI / 2, 1 / 1, 1, -100);
    gl.uniformMatrix4fv(perspectiveMatrixUniformLocation, false, perspectiveMatrix);

    //传入光照方向变换矩阵
    const lightTransformMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'lightTransformMatrix');
    gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);

    //传入法线变换矩阵
    const normalMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'normalMatrix');
    gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));

    //绘制初始图形
    gl.clearColor(0, 0, 0, 0.5);
    gl.enable(gl.DEPTH_TEST)
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);


    //功能相关函数
    function rotate_x() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t1 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateX(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_y() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t2 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateY(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_z() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t3 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateZ(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function stopRotate() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
    }

    function drawTriangle() {
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);
      gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));
      gl.drawElements(gl.TRIANGLES, 12, gl.UNSIGNED_SHORT, 0)
    }

    function getNormalMatrix(modelMatrix) {
      let invertMatrix = glMatrix.mat4.invert(glMatrix.mat4.create(), modelMatrix);
      return glMatrix.mat4.transpose(glMatrix.mat4.create(), invertMatrix);
    }

        点光源+旋转(片段着色器)

    // 获取WebGL上下文  
    const canvas = document.getElementById('webglCanvas');
    const gl = canvas.getContext('webgl');

    // 初始化着色器  
    const vertexShaderSource = `  
    attribute vec3 position;  
    uniform mat4 modelMatrix;
    uniform mat4 visionMatrix;
    uniform mat4 perspectiveMatrix;
    uniform mat4 normalMatrix;

    attribute vec3 normal;
    attribute vec3 color;

    varying vec3 vColor; 
    varying vec3 vNormal;
    varying vec3 vPosition;

    void main() {  
        gl_Position =perspectiveMatrix* visionMatrix * modelMatrix*  vec4(position, 1.0); 
        vColor = color;
        vPosition = position;
        vNormal = normalize((normalMatrix * vec4(normal,1.0)).xyz);
    }  
`;


    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);

    const fragmentShaderSource = `  
    precision mediump float; 

    uniform vec3 lightPosition;
    uniform vec3 cameraPosition;
    uniform vec3 lightColor;
     uniform mat4 lightTransformMatrix;

    varying vec3 vNormal; 
    varying vec3 vColor;
    varying vec3 vPosition;


    void main() {  

        vec3 finalNormal = normalize(vNormal);
        vec3 transLight = (lightTransformMatrix* vec4(lightPosition, 1.0)).xyz;
        vec3 lightVec = normalize(transLight-vPosition);
        vec3 cameraVec = normalize(cameraPosition-vPosition);
        vec3 halfVec = normalize(lightVec+cameraVec);
        float lightCos = max(dot(lightVec,vNormal),0.0);
        float lightCosHalf = max(dot(lightVec,halfVec),0.0);

        vec3 ambientLight = lightColor*0.5;
        vec3 diffuseLight = lightColor*lightCos*1.0;
        vec3 specularLight = lightColor*pow(lightCosHalf,20.0)*0.5;

        vec3 finalColor =(ambientLight+diffuseLight+specularLight)*vColor; 


        gl_FragColor = vec4(finalColor ,1.0); 
    }  
`;

    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);

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

    //初始化数据
    var transformMatrix = glMatrix.mat4.create();
    var t1, t2, t3 = null

    const vertices = new Float32Array([
      0, 0, -1,
      0, 0.942809, 0.333333,
      -0.816497, -0.471405, 0.333333,
      0.816497, -0.471405, 0.333333,

    ]);

    const indices = new Uint16Array([
      1, 2, 3,
      1, 2, 0,
      1, 3, 0,
      2, 3, 0,

    ]);

    const colors = new Float32Array([
      1, 0, 0,
      0, 1, 0,
      0, 0, 1,
      1, 1, 0,
    ])

    const normal = new Float32Array(
      [
        0, 0, -1,
        0, 0.942809, 0.333333,
        -0.816496, -0.471404, 0.333333,
        0.816496, -0.471404, 0.333333,
      ]
    )

    // 传入数据
    const vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'position');
    gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionAttributeLocation);

    const indicesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

    const colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

    const colorAttributeLocation = gl.getAttribLocation(shaderProgram, 'color');
    gl.vertexAttribPointer(colorAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(colorAttributeLocation);

    const normalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, normal, gl.STATIC_DRAW);

    const normalAttributeLocation = gl.getAttribLocation(shaderProgram, 'normal');
    gl.vertexAttribPointer(normalAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalAttributeLocation);

    //传入相机位置数据
    const cameraPoint = glMatrix.vec3.fromValues(2.0, 2.0, 3.0);
    const cameraPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'cameraPosition');
    gl.uniform3fv(cameraPositionVecUniformLocation, cameraPoint);

    //传入光源颜色数据
    const lightColor = glMatrix.vec3.fromValues(1.0, 1.0, 1.0);
    const lightColorVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightColor');
    gl.uniform3fv(lightColorVecUniformLocation, lightColor);

    //传入光源位置数据
    const lightPosition = glMatrix.vec3.fromValues(0.0, 5.0, 0.0);
    const lightPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightPosition');
    gl.uniform3fv(lightPositionVecUniformLocation, lightPosition);

    //传入模型变换矩阵
    const modelMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'modelMatrix');
    var modelMatrix = glMatrix.mat4.create();
    gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);

    //传入视图变换矩阵
    const visionMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'visionMatrix');
    const eye = cameraPoint;
    const look = glMatrix.vec3.fromValues(0, 0, 0);
    const up = glMatrix.vec3.fromValues(0, 1, 0);
    const visionMatrix = glMatrix.mat4.lookAt(glMatrix.mat4.create(), eye, look, up);
    gl.uniformMatrix4fv(visionMatrixUniformLocation, false, visionMatrix);

    //传入透视矩阵
    const perspectiveMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'perspectiveMatrix');
    const perspectiveMatrix = glMatrix.mat4.perspective(glMatrix.mat4.create(), Math.PI / 2, 1 / 1, 1, -100);
    gl.uniformMatrix4fv(perspectiveMatrixUniformLocation, false, perspectiveMatrix);

    //传入光照方向变换矩阵
    const lightTransformMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'lightTransformMatrix');
    gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);

    //传入法线变换矩阵
    const normalMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'normalMatrix');
    gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));

    //绘制初始图形
    gl.clearColor(0, 0, 0, 0.5);
    gl.enable(gl.DEPTH_TEST)
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);


    //功能相关函数
    function rotate_x() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t1 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateX(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_y() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t2 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateY(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_z() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t3 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateZ(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function stopRotate() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
    }

    function drawTriangle() {
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);
      gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));
      gl.drawElements(gl.TRIANGLES, 12, gl.UNSIGNED_SHORT, 0)
    }

    function getNormalMatrix(modelMatrix) {
      let invertMatrix = glMatrix.mat4.invert(glMatrix.mat4.create(), modelMatrix);
      return glMatrix.mat4.transpose(glMatrix.mat4.create(), invertMatrix);
    }

平行光(片段着色器)

    // 获取WebGL上下文  
    const canvas = document.getElementById('webglCanvas');
    const gl = canvas.getContext('webgl');

    // 初始化着色器  
    const vertexShaderSource = `  
    attribute vec3 position;  
    uniform mat4 modelMatrix;
    uniform mat4 visionMatrix;
    uniform mat4 perspectiveMatrix;
    uniform mat4 normalMatrix;

    attribute vec3 normal;
    attribute vec3 color;

    varying vec3 vColor; 
    varying vec3 vNormal;
    varying vec3 vPosition;

    void main() {  
        gl_Position =perspectiveMatrix* visionMatrix * modelMatrix*  vec4(position, 1.0); 
        vColor = color;
        vPosition = position;
        vNormal = normalize((normalMatrix * vec4(normal,1.0)).xyz);
    }  
`;


    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderSource);
    gl.compileShader(vertexShader);

    const fragmentShaderSource = `  
    precision mediump float; 

    uniform vec3 lightPosition;
    uniform vec3 cameraPosition;
    uniform vec3 lightColor;
     uniform mat4 lightTransformMatrix;

    varying vec3 vNormal; 
    varying vec3 vColor;
    varying vec3 vPosition;


    void main() {  

        vec3 finalNormal = normalize(vNormal);
        vec3 transLight = (lightTransformMatrix* vec4(lightPosition, 1.0)).xyz;
        vec3 lightVec = normalize(vec3(0.0,1.0,0.0));            //在此处直接将光源替换成固定方向即可
        vec3 cameraVec = normalize(cameraPosition-vPosition);
        vec3 halfVec = normalize(lightVec+cameraVec);
        float lightCos = max(dot(lightVec,vNormal),0.0);
        float lightCosHalf = max(dot(lightVec,halfVec),0.0);

        vec3 ambientLight = lightColor*0.5;
        vec3 diffuseLight = lightColor*lightCos*1.0;
        vec3 specularLight = lightColor*pow(lightCosHalf,20.0)*0.5;

        vec3 finalColor =(ambientLight+diffuseLight+specularLight)*vColor; 


        gl_FragColor = vec4(finalColor ,1.0); 
    }  
`;

    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    gl.compileShader(fragmentShader);

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

    //初始化数据
    var transformMatrix = glMatrix.mat4.create();
    var t1, t2, t3 = null

    const vertices = new Float32Array([
      0, 0, -1,
      0, 0.942809, 0.333333,
      -0.816497, -0.471405, 0.333333,
      0.816497, -0.471405, 0.333333,

    ]);

    const indices = new Uint16Array([
      1, 2, 3,
      1, 2, 0,
      1, 3, 0,
      2, 3, 0,

    ]);

    const colors = new Float32Array([
      1, 0, 0,
      0, 1, 0,
      0, 0, 1,
      1, 1, 0,
    ])

    const normal = new Float32Array(
      [
        0, 0, -1,
        0, 0.942809, 0.333333,
        -0.816496, -0.471404, 0.333333,
        0.816496, -0.471404, 0.333333,
      ]
    )

    // 传入数据
    const vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'position');
    gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionAttributeLocation);

    const indicesBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

    const colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);

    const colorAttributeLocation = gl.getAttribLocation(shaderProgram, 'color');
    gl.vertexAttribPointer(colorAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(colorAttributeLocation);

    const normalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, normal, gl.STATIC_DRAW);

    const normalAttributeLocation = gl.getAttribLocation(shaderProgram, 'normal');
    gl.vertexAttribPointer(normalAttributeLocation, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(normalAttributeLocation);

    //传入相机位置数据
    const cameraPoint = glMatrix.vec3.fromValues(2.0, 2.0, 3.0);
    const cameraPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'cameraPosition');
    gl.uniform3fv(cameraPositionVecUniformLocation, cameraPoint);

    //传入光源颜色数据
    const lightColor = glMatrix.vec3.fromValues(1.0, 1.0, 1.0);
    const lightColorVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightColor');
    gl.uniform3fv(lightColorVecUniformLocation, lightColor);

    //传入光源位置数据
    const lightPosition = glMatrix.vec3.fromValues(0.0, 5.0, 0.0);
    const lightPositionVecUniformLocation = gl.getUniformLocation(shaderProgram, 'lightPosition');
    gl.uniform3fv(lightPositionVecUniformLocation, lightPosition);

    //传入模型变换矩阵
    const modelMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'modelMatrix');
    var modelMatrix = glMatrix.mat4.create();
    gl.uniformMatrix4fv(modelMatrixUniformLocation, false, modelMatrix);

    //传入视图变换矩阵
    const visionMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'visionMatrix');
    const eye = cameraPoint;
    const look = glMatrix.vec3.fromValues(0, 0, 0);
    const up = glMatrix.vec3.fromValues(0, 1, 0);
    const visionMatrix = glMatrix.mat4.lookAt(glMatrix.mat4.create(), eye, look, up);
    gl.uniformMatrix4fv(visionMatrixUniformLocation, false, visionMatrix);

    //传入透视矩阵
    const perspectiveMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'perspectiveMatrix');
    const perspectiveMatrix = glMatrix.mat4.perspective(glMatrix.mat4.create(), Math.PI / 2, 1 / 1, 1, -100);
    gl.uniformMatrix4fv(perspectiveMatrixUniformLocation, false, perspectiveMatrix);

    //传入光照方向变换矩阵
    const lightTransformMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'lightTransformMatrix');
    gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);

    //传入法线变换矩阵
    const normalMatrixUniformLocation = gl.getUniformLocation(shaderProgram, 'normalMatrix');
    gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));

    //绘制初始图形
    gl.clearColor(0, 0, 0, 0.5);
    gl.enable(gl.DEPTH_TEST)
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);


    //功能相关函数
    function rotate_x() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t1 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateX(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_y() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t2 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateY(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function rotate_z() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
      t3 = setInterval(function () {
        let rotateMatrix = glMatrix.mat4.rotateZ(glMatrix.mat4.create(), glMatrix.mat4.create(), -Math.PI / 200);
        transformMatrix = glMatrix.mat4.multiply(glMatrix.mat4.create(), rotateMatrix, transformMatrix);
        drawTriangle();
      }, 10)
    }

    function stopRotate() {
      clearInterval(t1);
      clearInterval(t2);
      clearInterval(t3);
    }

    function drawTriangle() {
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.uniformMatrix4fv(lightTransformMatrixUniformLocation, false, transformMatrix);
      gl.uniformMatrix4fv(normalMatrixUniformLocation, false, getNormalMatrix(modelMatrix));
      gl.drawElements(gl.TRIANGLES, 12, gl.UNSIGNED_SHORT, 0)
    }

    function getNormalMatrix(modelMatrix) {
      let invertMatrix = glMatrix.mat4.invert(glMatrix.mat4.create(), modelMatrix);
      return glMatrix.mat4.transpose(glMatrix.mat4.create(), invertMatrix);
    }

;