当前位置: 首页 > web >正文

【OpenGL】LearnOpenGL学习笔记11 - 多光源

上接:https://blog.csdn.net/weixin_44506615/article/details/150446490?spm=1001.2014.3001.5501
完整代码:https://gitee.com/Duo1J/learn-open-gl

在上一节中,我们都是用单一光源来进行绘制的,接下来我们将三种光源都使用起来
直接上代码

1. 平行光

这里我们用到了GLSL的函数,其定义和使用方式和C一样
我们在CalcDirectionalLight中计算了平行光的各分量,并加起来返回

// 平行光
struct DirLight {vec3 ambient;vec3 diffuse;vec3 specular;vec3 direction;
};uniform DirLight dirLight;// 计算平行光
vec3 CalcDirectionalLight(DirLight light, vec3 normal, vec3 viewDir)
{vec3 lightDir = normalize(-light.direction);// 环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));// 漫反射float diff = max(dot(normal, lightDir), 0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));// 镜面反射vec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(reflectDir, viewDir), 0), material.shininess);vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));return ambient + diffuse + specular;
}

2. 点光源

我们将会使用4个点光源,使用uniform声明数组

// 点光源
struct PointLight {vec3 ambient;vec3 diffuse;vec3 specular;vec3 position;float constant;float linear;float quadratic;
};#define POINT_LIGHT_NUM 4
uniform PointLight pointLight[POINT_LIGHT_NUM];// 计算点光源
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 viewDir, vec3 fragPos)
{vec3 lightDir = normalize(light.position - fragPos);// 衰减系数float d = length(light.position - fragPos);float attenuation = 1 / (light.constant + light.linear * d + light.quadratic * d * d);// 环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)) * attenuation;// 漫反射float diff = max(dot(normal, lightDir), 0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)) * attenuation;// 镜面反射vec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(reflectDir, viewDir), 0), material.shininess);vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)) * attenuation;return ambient + diffuse + specular;
}

3. 聚光灯

// 聚光灯
struct SpotLight {vec3 ambient;vec3 diffuse;vec3 specular;vec3 position;vec3 direction;float cutOff;float cutOffOuter;float constant;float linear;float quadratic;
};uniform SpotLight spotLight;// 计算聚光灯
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 viewDir, vec3 fragPos)
{vec3 lightDir = normalize(light.position - fragPos);// 强度float theta_cos = dot(lightDir, -normalize(light.direction));float intensity = clamp((theta_cos - light.cutOffOuter) / (light.cutOff - light.cutOffOuter), 0, 1);// 衰减float d = length(light.position - FragPos);float attenuation = 1 / (light.constant + light.linear * d + light.quadratic * d * d);// 环境光vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)) * attenuation * intensity;// 漫反射float diff = max(dot(normal, lightDir), 0);vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)) * attenuation * intensity;// 镜面反射vec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(reflectDir, viewDir), 0), material.shininess);vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)) * attenuation * intensity;return ambient + diffuse + specular;
}

4. 合并

void main()
{vec3 normal = normalize(Normal);vec3 viewDir = normalize(viewPos - FragPos);// 平行光vec3 result = CalcDirectionalLight(dirLight, normal, viewDir);// 点光源for (int i = 0; i < POINT_LIGHT_NUM; i++){result += CalcPointLight(pointLight[i], normal, viewDir, FragPos);}// 聚光灯result += CalcSpotLight(spotLight, normal, viewDir, FragPos);FragColor = vec4(result, 1.0f);
}

5. C++ 传递数据

首先声明点光源位置数组

// 点光源位置
glm::vec3 pointLightPositions[] = {glm::vec3(0.7f,  0.2f,  2.0f),glm::vec3(2.3f, -3.3f, -4.0f),glm::vec3(-4.0f,  2.0f, -12.0f),glm::vec3(0.0f,  0.0f, -3.0f)
};

传递平行光数据

shader.SetVec3("dirLight.ambient", glm::vec3(0.05f));
shader.SetVec3("dirLight.diffuse", glm::vec3(0.4f));
shader.SetVec3("dirLight.specular", glm::vec3(0.5f));
shader.SetVec3("dirLight.direction", glm::vec3(-0.2f, -1.0f, -0.3f));

传递点光源数据

for (int i = 0; i < 4; i++)
{std::stringstream ss;shader.SetVec3("pointLight[" + std::to_string(i) + "].ambient", glm::vec3(0.05f));shader.SetVec3("pointLight[" + std::to_string(i) + "].diffuse", glm::vec3(0.8f));shader.SetVec3("pointLight[" + std::to_string(i) + "].specular", glm::vec3(1.0f));shader.SetVec3("pointLight[" + std::to_string(i) + "].position", glm::vec3(pointLightPositions[i]));shader.SetFloat("pointLight[" + std::to_string(i) + "].constant", 1.0f);shader.SetFloat("pointLight[" + std::to_string(i) + "].diffuse", 0.09f);shader.SetFloat("pointLight[" + std::to_string(i) + "].quadratic", 0.032f);
}

传递聚光灯数据

shader.SetVec3("spotLight.ambient", glm::vec3(0));
shader.SetVec3("spotLight.diffuse", glm::vec3(1));
shader.SetVec3("spotLight.specular", glm::vec3(1));shader.SetVec3("spotLight.position", camera.transform.position);
shader.SetVec3("spotLight.direction", camera.transform.front);shader.SetFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
shader.SetFloat("spotLight.cutOffOuter", glm::cos(glm::radians(17.5f)));
shader.SetFloat("spotLight.constant", 1.0f);
shader.SetFloat("spotLight.linear", 0.09f);
shader.SetFloat("spotLight.quadratic", 0.032f);

绘制点光源模型,方便观察

for (int i = 0; i < 4; i++)
{lightShader.Use();glm::mat4 model = glm::mat4(1.0f);model = glm::translate(model, glm::vec3(pointLightPositions[i]));model = glm::scale(model, glm::vec3(0.1f));lightShader.SetMat4("model", model);lightShader.SetMat4("view", view);lightShader.SetMat4("projection", projection);lightShader.SetVec3("objectColor", lightColor);glBindVertexArray(lightVAO);glDrawArrays(GL_TRIANGLES, 0, 36);
}

编译运行,顺利的话可以看见以下图像
平行光 + 点光源 + 聚光灯
多光源
只有平行光

平行光 + 点光源

平行光 + 聚光灯

完整代码可在顶部git仓库中找到

http://www.xdnf.cn/news/18158.html

相关文章:

  • Linux入门指南:基础开发工具---vim
  • mysql建库规范
  • 《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
  • 基于Vue + Node能源采购系统的设计与实现/基于express的能源管理系统#node.js
  • 数据结构与算法:线段树(一):基本原理
  • 【Python练习】097. 编写一个函数,实现简单的版本控制工具
  • 机器人经验学习1 杂记
  • 牛客周赛 Round 105
  • Vue 与 React 深度对比:设计哲学、技术差异与应用场景
  • 深度学习·GFSS
  • 基于RK3588的微电网协调控制器:实现分布式能源的智能调控与优化运行
  • JavaScirpt高级程序设计第三版学习查漏补缺(1)
  • MysqL(二:sqL调优)
  • 《若依》介绍和环境搭建
  • 低空经济产业链全景解析
  • 软考 系统架构设计师系列知识点之杂项集萃(125)
  • MySQL性能优化:10个关键参数调整指南
  • 基于STM32的精确按键时长测量系统
  • 无痕HOOK 检测及对抗
  • Altium Designer 22使用笔记(7)---网表导入,叠层设置
  • 解密红外温度芯片的“工作环境温度” 范围
  • 在openEuler24.03 LTS上高效部署Apache2服务的完整指南
  • CPP多线程1:C++11的std::thread
  • LakeHouse--湖仓一体架构
  • 防御保护16
  • 【更新公告】C++算法·线段树
  • CSDN部分内容改为视频转到B站-清单
  • 容器化部署:用Docker封装机器翻译模型与服务详解
  • NY243NY253美光固态闪存NY257NY260
  • AI的下一个竞争焦点——世界模型