OpenGL程序员今日看点

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

2016-10-26  本文已影响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

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

方向光

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

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;
}
上一篇下一篇

猜你喜欢

热点阅读