【learnOpenGL学习笔记_15】OpenGL模型加载实战 - 从零到一实现复杂模型渲染,加光照更好看

大家好,我是 同学小张,+v: jasper_8017 一起交流,持续学习AI大模型应用实战案例,持续分享,欢迎大家点赞+关注,订阅我的大模型专栏,共同学习和进步。
欢迎订阅专栏,即将涨价!


上篇文章我们实现了 Assimp 模型库的安装,并使用 Assimp 模型库加载了一个模型并进行了渲染。本文我们在此基础上,添加光照效果,巩固下学到的知识。

1. 修改顶点着色器

点光源的光照计算,需要知道法线方向和片段着色器位置,所以我们在顶点着色器中输出这两个值。

out vec3 outNormal; // 输出法线位置
out vec3 outFragPos; // 输出片段着色器位置

......

outFragPos = vec3(model * vec4(aPos, 1.0));
outNormal = aNormal;

2. 修改片段着色器

在片段着色器中,我们使用点光源的光照计算函数,计算每个点光源对当前片段着色器的影响,并累加到最终颜色中。主要的修改如下:

(1)接收法线和片段着色器位置

(2)定义点光源结构体和点光源数组

(3)点光源光照计算需要 viewPos 变量

(4)实现点光源光照计算函数

(5)点光源数组遍历,计算每个点光源对当前片段着色器的影响,最后累加到最终颜色中。

......

in vec3 outNormal;
in vec3 outFragPos;

struct PointLight {
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
};
#define NR_POINT_LIGHTS 4
uniform PointLight pointLights[NR_POINT_LIGHTS];

uniform vec3 viewPos;

vec3 calculatePointLight(PointLight light, vec3 normal, vec3 viewDir, vec3 fragPos)
{
    vec3 lightDir = normalize(light.position - fragPos);
    // 计算漫反射强度
    float diff = max(dot(normal, lightDir), 0.0);
    // 计算镜面反射
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // 计算衰减
    float distance = length(light.position - fragPos);
    float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
    // 将各个分量合并
    vec3 ambient  = light.ambient  * vec3(texture(material.diffuse, TexCoords));
    vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, TexCoords));
    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    ambient  *= attenuation;
    diffuse  *= attenuation;
    specular *= attenuation;
    return (ambient + diffuse + specular);
}

void main()
{    
    vec3 normal = normalize(outNormal);
    vec3 viewDir = normalize(viewPos - outFragPos);

    vec3 finalColor = vec3(0.0);
    for(int i = 0; i < NR_POINT_LIGHTS; i++)
    {
        finalColor += calculatePointLight(pointLights[i], normal, viewDir, outFragPos);
    }

    color = vec4(finalColor, 1.0);
}

3. 修改 C++ 代码

(1)在片段着色器中,我们使用了 viewPos 变量,所以需要在 C++ 代码中设置这个变量。

(2)在片段着色器中,我们使用了 PointLight 结构体,所以需要在 C++ 代码中设置这个结构体。

......

// 点光源
glm::vec3 lightColor = glm::vec3(1.0f, 0.0f, 1.0f);
ourShader.setVec3("pointLights[0].ambient"
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

同学小张

如果觉得有帮助,欢迎给我鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值