美文网首页
OpenGL ES 光照模型(一)

OpenGL ES 光照模型(一)

作者: ZerLon51 | 来源:发表于2017-05-10 23:27 被阅读0次

    关于光照模型的总结,我就不一一细谈了,一是自己记不住那么多,二呢,我觉得知识还是要实践为主。所以以下的东西主要针对编程而言的,不会涉及很综合深刻的讲解。照例最后可以猛戳下载代码。
    1.漫反射
    漫反射光大概就是从光源照射到物体表面,不考虑人的观察视角与反射的角度形成的光源强弱差别,而只考虑光源入射角和顶点法线的夹角,在各个方向上均等的反射光线的一种光。
    假设Ld表示光源强度,Kd表示某个物体的反射系数,那么漫反射公式就是
    Ia = Ld * Kd * cos(b)
    如下图


    漫反射

    那么s和n的点乘就表示夹角的cos了(有疑惑的翻翻几何课本),于是就有公式如下


    漫反射公式

    有了这个公式,我们愉快的开始写代码吧!

    attribute vec3 vertPosition; // Vertex position
    attribute vec3 vertNorm; // Vertex normal
    
    varying vec3 lightIntensity; // Light intensity
    
    uniform vec3 lightPosition; // Light position in eye - coordinate
    uniform vec3 Kd; // Reflect of diffuse light
    uniform vec3 Ld; // Intensity of light
    
    uniform mat3 normMat; // matrix of normal
    uniform mat4 modelview; // matrix of modelview
    uniform mat4 projection; // matrix of projection
    
    void main() {
        // Convert normal and position to eye coord
        vec3 tnorm = normalize(normMat * vertNorm);
        vec3 eyecoord = vec3(modelview * vec4(vertPosition, 1.0));
        vec3 s = normalize(lightPosition - eyecoord);
        
        // The diffuse shading equation
        lightIntensity = Ld * Kd * max(dot(s, tnorm), 0.0);
        
        gl_Position = projection * modelview * vec4(vertPosition, 1.0);
    }
    

    接下来,说代码吧。
    前两行的attribute变量用于定义顶点坐标和顶点法线,也就是我们届时要输入的值。这里一定要注意,这个shader文件里的处理流程是逐顶点的,就是每次处理一个顶点变换。
    然后定义一个varying输出变量,一会儿在fragment shader中要用到的。
    之后是光源坐标Position,这里已经转换为观察坐标了,你也可以在shader里面转换。然后就是光照强度La,反射系数Kd。
    接着定义了法线变换矩阵。这个东西简单讲一下。


    我扣的图
    类似于图中的法线,在图被拉伸(还有旋转什么的,法线要跟着顶点动才对)了之后,法线的方向就错了,因此需要法线矩阵来变换一下。法线矩阵的推导公式就不列出来了,线性代数我还在复习,也讲不太好,网上有不少资料,能看懂就好了。刚体变换就用观察矩阵modelview的左上角3x3就可以了。
    然后定义了观察变换矩阵和投影变换矩阵。
    然后,鸡冻人心的时刻就到了。
    首先我们用法线矩阵变换顶点法向量,观察矩阵变换顶点坐标

        vec3 tnorm = normalize(normMat * vertNorm);
        vec3 eyecoord = vec3(modelview * vec4(vertPosition, 1.0));
    

    然后计算指向光源坐标的向量,并且归一化

        vec3 s = normalize(lightPosition - eyecoord);
    

    接着,就要用到我们上面的公式了

        lightIntensity = Ld * Kd * max(dot(s, tnorm), 0.0);
    

    这个lightIntensity一会儿就是我们计算出来的顶点颜色。
    接下来,使用gl_Position输出最终经过观察->投影变换后的顶点坐标

        gl_Position = projection * modelview * vec4(vertPosition, 1.0);
    

    至此,顶点shader的工作就完成了。

    然后开始处理片段shader了。
    上代码

    precision mediump float;
    
    varying vec3 lightIntensity;
    
    void main() {
        gl_FragColor = vec4(lightIntensity, 1.0);
    }
    

    其中定义的varying vec3 lightIntensity就是我们在vertex shader中计算出来的光照后的顶点颜色值。最终赋值给gl_FragColor,就是顶点的最后颜色了。
    然后让程序跑起来,最终结果如下

    渲染结果

    另外代码中的ToyMater/ToyTest目录下是测试用的,可以很方便的修修改改的来测试。

    猛戳代码

    相关文章

      网友评论

          本文标题:OpenGL ES 光照模型(一)

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