美文网首页OpenGL程序员今日看点
OpenGL ES 3.0编程指南:第八章. Vertex Sh

OpenGL ES 3.0编程指南:第八章. Vertex Sh

作者: 别卡机 | 来源:发表于2016-10-26 12:06 被阅读178次

    [TOC]

    2. Vertex Shader Examples

    接下来通过一些实例来说明如何在顶点shader中实现下列功能:

    • 用矩阵来变换顶点坐标
    • 光照计算,生成逐顶点漫反射和高光反射
    • 生成纹理坐标
    • 顶点蒙皮
    • 使用纹理查找值来代替顶点位置

    Matrix Transformations

    Example 8-1:

    #version 300 es
    
    uniform mat4 u_mvpMatrix;
    
    layout(location = 0) in vec4 a_position;
    layout(location = 1) in vec4 a_color;
    
    out vec4 v_color;
    
    void main()
    {
        v_color = a_color;
        gl_Position = u_mvpMatrix * a_position;
    }
    

    在第七章我们已经介绍过,顶点shader的输入位置是在物体坐标系中,输出位置是在裁剪坐标系中,这种变换是通过一个MVP矩阵来实现的:

    • 模型矩阵:将物体坐标转换为世界坐标
    • 视图矩阵:将世界坐标转换为视口坐标(眼睛坐标、摄像机坐标)
    • 投影矩阵:将视口坐标转换为裁剪坐标

    Lighting in a Vertex Shader

    • 漫反射光照计算



      漫反射光照颜色 = 光照强度 * 光照颜色 * cos(光照与法线夹角)

    • 镜面反射-Phong



    镜面反射特性:当R与V重合时光照最强,稍微有一点偏差就会有很大的衰减。
    镜面反射光照颜色 = pow(dot(R, V), 光照颜色)

    • 镜面反射-BlinnPhong



      镜面反射光照颜色 = pow(dot(H, N), 光照颜色)

    方向光

    方向光,也叫平行光,是一个距离被照明物体无限远的光源,比如太阳光。由于距离物体无限远,所以方向光的光线都是平行的,照明方向向量是一个常量,不需要逐顶点计算。

    Example 8-2

    #version 300 es
    
    struct directional_light
    {
        vec3 direction;    // normalized
        vec3 halfplane;    // normalized
        vec4 ambient_color;
        vec4 diffuse_color;
        vec4 specular_color;
    };
    
    struct material_properties
    {
        vec4 ambient_color;
        vec4 diffuse_color;
        vec4 specular_color;
        float specular_exponent
    };
    
    const float c_zero = 0.0;
    const float c_one = 1.0;
    
    uniform material_properties material;
    uniform directional_light light;
    
    vec4 directional_light_color (vec3 normal)
    {
        vec4 computer_color = vec4 (c_zero, c_zero, c_zero, c_zero);
        
        float NdotL = max (c_zero, dot (normal, light.direction));
        float NdotH = max (c_zero, dot (normal, light.halfplane));
    
        computer_color += light.ambient_color * material.ambient_color;    //环境光
        computer_color += NdotL * light.diffuse_color * material.diffuse_color;   //漫反射光
        
        if (NdotH > 0) {
            computer_color += pow(NdotH, material.specular_exponent) * material.specular_color * light.specular_color;   //镜面高光
       }
    
        return computer_color;
    }
    

    点光源和聚光灯

    点光源是空间中某个位置向所有方向均匀发射光线的光源,由一个位置向量(x, y, z, w)指定,其中w≠0。点光源在各个方向上的亮度均匀,但是随着距离的递增,亮度递减,这种递减可用如下公式计算:

    <center><font size = 4> 距离衰减 = 1 / (K0 + K1 * ||VPlight|| + K2 * ||VPlight||2 ) </font></center>

    聚光灯是同时拥有位置和方向的锥体光源,如下图所示:



    聚光灯的光照强度由光锥中轴向周围递减,衰减因子在光锥中轴为1,在光锥边缘按照指数关系衰减为0。

    Example 8-3 Spotlight

    #version 300 es
    
    struct spot_light
    {
        vec4 position;
        vec4 ambient_color;
        vec4 diffuse_color;
        vec4 specular_color;
        vec3 spot_direction;
        vec3 attenuation_factors;    //距离衰减因子K<sub>0</sub>,K<sub>1</sub>,K<sub>2</sub>
        bool compute_distance_attenuation;
        float spot_exponent;
        float spot_cutoff_angle;
    };
    
    struct material_properties
    {
        vec4 ambient_color;
        vec4 diffuse_color;
        vec4 specular_color;
        float specular_exponent;
    };
    
    const float c_zero = 0.0;
    const float c_one = 1.0;
    
    uniform material_properties material;
    uniform spot_light light;
    
    vec4 spot_light_color (vec3 normal, vec4 position)
    {
        vec4 computed_color = vec4 (c_zero, c_zero, c_zero, c_zero);
        
        vec3 lightDir;
        vec3 halfplane;
        float NdotL, NdotH;
        float att_factor;
    
        att_factor = c_one;
        lightDir = light.position.xyz - position.xyz;
    
        if (light. compute_distance_attenuation) {
            vec3 att_dist;
            att_dist.x = 1;
            att_dist.z = dot (lightDir, lightDir);
            att_dist.y = sqrt(att_dist.z);    
            att_factor = c_one / dot(att_dist, light.attenuation_factors);
       }
    
        lightDir = normalize (lightDir);
    
        if (light.spot_cutoff_angle < 180.0) {
            float spot_factor = dot (-lightDir, light.spot_direction);
            if (spot_factor >= cos(radians(light.spot_cutoff_angle)) )
                spot_factor = pow (spot_factor, light.spot_exponent);
            else
                spot_factor = c_zero;
    
            att_factor *= spot_factor;
        }
    
        if (att_factor > c_zero) {
            computed_color += light.ambient_color * material.ambient_color;
            
           NdotL = max(c_zero, dot(normal, lightDir));
            computed_color += NdotL * light.diffuse_color * material.diffuse_color;
            
            halfplane = normailze (lightDir + vec3(c_zero, c_zero, c_one));
            NdotH = dot (normal, halfplane);
            if (NdotH > c_zero) {
                computed_color += pow (NdotH, material.specular_exponent) * material.specular_color * light.specular_color;
           }
            
            computed_color *= att_factor;
       }
        
        return computed_color;
    }
    

    相关文章

      网友评论

        本文标题:OpenGL ES 3.0编程指南:第八章. Vertex Sh

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