美文网首页
2022-10-13 phong光照模型

2022-10-13 phong光照模型

作者: MrSwilder | 来源:发表于2022-10-12 00:05 被阅读0次

    一、原理

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

    镜面光计算

    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

    相关文章

      网友评论

          本文标题:2022-10-13 phong光照模型

          本文链接:https://www.haomeiwen.com/subject/mmwxzrtx.html