2022-10-13 phong光照模型

2022-10-12  本文已影响0人  MrSwilder

一、原理

环境光+漫反射光+镜面光

镜面光计算

1)根据入射光方向(lightDirection)和法线(v_Normal)计算反射光方向reflectDirection

 vec3 reflectDirection =reflect(normalize(-lightDirection),normalize(v_Normal.rgb));

2)计算反射光(reflectDirection) 与视线(viewDir)夹角

 float specAmt=max(0.0,dot(viewDir,reflectDirection));

3)根据反光系数进行指数运算specBrightness

  float specBrightness=pow(specAmt,128.0);

4)基底色光线颜色specBrightness

vec3 specularColor=baseColor*u_LightColor*specBrightness;

二、代码

 //顶点着色器
    var VSHADER_SOURCE = /*glsl*/ `
      attribute vec4 a_Position;
      attribute vec4 a_Color;
      attribute vec2 a_Uv;
      attribute vec4 a_Normal;

      uniform mat4 u_ModelMatrix;
      uniform mat4 u_ViewMatrix;
      uniform mat4 u_ProjectMatrix;
      uniform mat4 u_MvpMatrix;
        uniform mat4 u_NormalMatrix;
      varying vec4 v_Color;
      varying vec2 v_Uv;
      varying vec4 v_Normal;
      varying vec4 v_Position;
      void main(){
        mat4 mvpMatrix=u_ProjectMatrix*u_ViewMatrix*u_ModelMatrix;
         gl_Position = mvpMatrix * a_Position;
         v_Color = a_Color;
         v_Uv=a_Uv;
         v_Normal=u_NormalMatrix*a_Normal;
            // v_Normal=a_Normal;
         v_Position=u_ModelMatrix*a_Position;
      }`;

    //片元着色器
    var FSHADER_SOURCE = /*glsl*/ `
      #ifdef GL_ES
      precision mediump float;
      #endif
      varying vec4 v_Color;
      uniform sampler2D u_Texture;
    //   uniform vec3 u_LightDirection;
      uniform vec3 u_LightPosition;
      uniform vec3 u_LightColor;
      uniform vec3 u_ViewPosition;
      varying vec2 v_Uv;
      varying vec4 v_Normal;
      varying vec4 v_Position;
      void main(){
        vec3 baseColor= texture2D(u_Texture,v_Uv).rgb;

        //计算光照方向
        vec3 lightDirection=u_LightPosition-v_Position.xyz;
        
        // vec3 baseColor=vec3(1.0);
        //计算漫反射光
        float dotL=max(0.0,dot(normalize(lightDirection),normalize(v_Normal.rgb)));
        vec3 diffuseColor=baseColor*u_LightColor*dotL;

        //计算镜面反射光
        //计算反射光
        vec3 reflectDirection =reflect(normalize(-lightDirection),normalize(v_Normal.rgb));
        //计算片元到相机的方向
        vec3 viewDir=normalize(u_ViewPosition-v_Position.xyz);
        float specAmt=max(0.0,dot(viewDir,reflectDirection));
        float specBrightness=pow(specAmt,128.0);
        vec3 specularColor=baseColor*u_LightColor*specBrightness;

         gl_FragColor =vec4(diffuseColor+specularColor+vec3(0.3)*baseColor,1.0);
      }`;

    //声明js需要的相关变量
    var canvas = document.getElementById("canvas");
    var gl = getWebGLContext(canvas);

    async function main() {
        if (!gl) {
            console.log("你的浏览器不支持WebGL");
            return;
        }

        const program = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE);
        if (!program) {
            console.warn("创建程序失败!");
            return;
        }

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

        //获取内置变量的信息
        getVariableLocation(program);

        var n = createCube(gl);
        if (n < 0) {
            console.log("无法创建缓冲区");
            return;
        }
        console.log(n);
        //设置底色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);

        //初始化纹理
        await initTexture(gl, "./image/box.jpg", 0);

        //设置光照
        //   const lightDirection = gl.getUniformLocation(program, "u_LightDirection");
        //   gl.uniform3fv(lightDirection, [-5, 0, -5]);

        //设置点光源
        const lightPosition = gl.getUniformLocation(program, "u_LightPosition");
        gl.uniform3fv(lightPosition, [-3, -1, 3]);


        const lightColor = gl.getUniformLocation(program, "u_LightColor");
        gl.uniform3fv(lightColor, [1, 1, 1]);

        //根据时间绘制
        var tick = function () {
            //变换角度
            currentAngle = animate(currentAngle)
            // gl.enable(gl.BLEND)
            gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA)
            //绘制三角形
            draw(gl, 36, currentAngle);
            //重复请求
            requestAnimationFrame(tick)
        }
        tick()


    }


    var g_last = Date.now()
    var currentAngle = 0
    function animate(currentAngle) {

        //获取当前时间
        var currentTime = Date.now()
        timeD = currentTime - g_last
        g_last = currentTime

        //计算旋转的角度
        currentAngle = currentAngle + (timeD * 30) / 1000
        return currentAngle %= 360
    }

    function draw(gl, n, currentAngle) {
        const program = gl.program;
        //设置视角矩阵的相关信息(视点,视线,上方向)
        var viewMatrix = new Matrix4();
        viewMatrix.setLookAt(3, 3, 7, 0, 0, 0, 0, 1, 0);

        const viewPosition = gl.getUniformLocation(program, "u_ViewPosition");
        gl.uniform3fv(viewPosition, [3, 3, 7]);

        //设置模型矩阵的相关信息
        var modelMatrix = new Matrix4();
        modelMatrix.setRotate(currentAngle, 0, 1, 0);

        var normalMatrix = new Matrix4()

        normalMatrix.transpose(normalMatrix.setInverseOf(modelMatrix))

        //设置透视投影矩阵
        var projMatrix = new Matrix4();
        projMatrix.setPerspective(30, canvas.width / canvas.height, 1, 100);

        //将试图矩阵传给u_ViewMatrix变量
        // gl.uniformMatrix4fv(program.mvpMatrix, false, projMatrix.elements);
        gl.uniformMatrix4fv(program.modelMatrix, false, modelMatrix.elements);
        gl.uniformMatrix4fv(program.viewMatrix, false, viewMatrix.elements);
        gl.uniformMatrix4fv(program.projectMatrix, false, projMatrix.elements);
        gl.uniformMatrix4fv(program.normalMatrix, false, normalMatrix.elements);

        //开启隐藏面清除
        gl.enable(gl.DEPTH_TEST);

        //清空颜色和深度缓冲区
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        //绘制图形
        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
    }

三、效果

phong.gif
上一篇下一篇

猜你喜欢

热点阅读