OpenGL学习12——光线投射器

2021-06-26  本文已影响0人  蓬篙人

光线投射器(Light Casters)

目前我们的渲染场景都只是应用单一来源的光源,现实世界中往往存在多种类型的光源。一个投射光线到物体上的光源我们称为光线投射器(light caster)。下面我们讨论几种光线投射器。

1. 定向光源

struct Light{
    // vec3 position;  // 对于方向光源,不需要位置矢量
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
...
void main()
{
    vec3 lightDir = normalize(-light.direction);  // 直接取反
    // 下面直接使用lightDir计算扩散光和镜面光
    ...
}
for (unsigned int i = 0; i < 10; i++)
{
    glm::mat4 model = glm::mat4(1.0f);
    model = glm::translate(model, cubePositions[i]);
    float angle = 20.0f * i;
    model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
    objectShader.setMat4("model", model);
    glDrawArrays(GL_TRIANGLES, 0, 36);
}
objectShader.setVec3("light.direction", -0.2f, -1.0f, -0.3f);

2. 点光源

距离 常数项 线性项 二次项
7 1.0 0.7 1.8
13 1.0 0.35 0.44
20 1.0 0.22 0.20
32 1.0 0.14 0.07
50 1.0 0.09 0.032
65 1.0 0.07 0.017
100 1.0 0.045 0.0075
160 1.0 0.027 0.0028
200 1.0 0.022 0.0019
325 1.0 0.014 0.0007
600 1.0 0.007 0.0002
3250 1.0 0.0014 0.00007
struct Light{
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;

    float constant;
    float linear;
    float quadratic;
};
// 使用GLSL内置函数length
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
objectShader.setFloat("light.constant", 1.0f);
objectShader.setFloat("light.linear", 0.09f);
objectShader.setFloat("light.quadratic", 0.032f);

3. 聚光灯(spotlight)

struct Light{
    vec3 position;
    vec3 direction;
    float cutOff;
    ...
};
float theta = dot(lightDir, normalize(-light.direction));
if(theta > light.cutOff)
{
    // 完成光源计算
}
else
{
    FragColor = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0);
}
objectShader.setVec3("light.position", camera.Position);
objectShader.setVec3("light.direction", camera.Front);
objectShader.setFloat("light.cutOff", glm::cos(glm::radians(12.5f)));

4. 聚光灯边缘平滑

\theta \theta角度 \phi(内cutoff) \phi角度 \gamma(外cutoff) \gamma角度 \epsilon I
0.87 30 0.91 25 0.82 35 0.91 - 0.82 =
0.09
0.87 - 0.82 /
0.09 = 0.56
0.9 26 0.91 25 0.82 35 0.91 - 0.82 =
0.09
0.9 - 0.82 /
0.09 = 0.89
0.97 14 0.91 25 0.82 35 0.91 - 0.82 =
0.09
0.97 - 0.82 /
0.09 = 1.67
0.83 34 0.91 25 0.82 35 0.91 - 0.82 =
0.09
0.83 - 0.82 /
0.09 = 0.11
0.64 50 0.91 25 0.82 35 0.91 - 0.82 =
0.09
0.64 - 0.82 /
0.09 = -2.0
0.966 15 0.9978 12.5 0.953 17.5 0.996 - 0.953 =
0.0448
0.966 - 0.953 /
0.0448 = 0.29
struct Light{
    vec3 position;
    vec3 direction;
    float cutOff;
    float outerCutOff;
    ...
};

int main()
{
    float theta = dot(lightDir, normalize(-light.direction));
    float epsilon = light.cutOff - light.outerCutOff;
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); 

    ...

    diffuse *= intensity;
    specular *= intensity;
    ...
}
objectShader.setFloat("light.cutOff", glm::cos(glm::radians(12.5f)));
objectShader.setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f)));
上一篇下一篇

猜你喜欢

热点阅读