LearnOpenGL-光照-6.多光源
创始人
2024-06-01 16:12:37
0

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject

文章目录

  • 前言
  • 例子
    • 代码
    • 没有聚光灯效果
    • 有聚光灯效果

前言

  • 此节目的

    综合2.5投光物,在此节实现一个场景使用多个光源,物体根据不同光源而叠加颜色

    • 熟悉多光源如何计算物体颜色
    • 熟悉用glsl函数

例子

代码

  • glsl

    #version 330 core
    out vec4 FragColor;
    struct Material {sampler2D diffuse;  // 漫反射颜色分量从纹理采样sampler2D specular;//  镜面光照颜色分量从纹理采样float shininess;
    }; 
    // 平行光
    struct DirLight  {vec3 direction; // 从光源出发到全局的方向vec3 ambient;vec3 diffuse;vec3 specular;
    };
    // 点光源
    struct PointLight  {vec3 position;  vec3 ambient;vec3 diffuse;vec3 specular;float constant; // 常数float linear;   // 一次项float quadratic;// 二次项
    };uniform DirLight dirLight;
    #define NR_POINT_LIGHTS 4
    uniform PointLight pointLights[NR_POINT_LIGHTS];uniform Material material;in vec3 FragPos;
    in vec3 Normal;
    in vec2 TexCoords;// 纹理坐标uniform vec3 viewPos;// 计算平行光影响当前片段的颜色
    vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir){vec3 lightDir = normalize(-light.direction);// 取负变为光源的方向向量,用在计算漫反射和镜面光分量时// 漫反射光照分量float diff = max(dot(normal, lightDir), 0.0);// 得到光源对当前片段实际的漫反射影响// 镜面光光照分量vec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// 从纹理读取颜色分量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));return (ambient + diffuse + specular);
    }
    // 计算点光源影响当前片段的颜色
    vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir){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.0 / (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 norm = normalize(Normal);vec3 viewDir = normalize(viewPos - FragPos);// 平行光vec3 result = CalcDirLight(dirLight, norm, viewDir);// 点光源for(int i = 0; i < NR_POINT_LIGHTS; i++){result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);}FragColor = vec4(result, 1.0);
    }
    
  • cpp

    lightingShader.use();
    lightingShader.setInt("material.diffuse", 0);
    lightingShader.setInt("material.specular", 1);
    lightingShader.setFloat("material.shininess", 32.0f);
    // 平行光
    lightingShader.setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f);
    lightingShader.setVec3("dirLight.ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setVec3("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
    lightingShader.setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f);// 点光源
    lightingShader.setVec3("pointLights[0].position", pointLightPositions[0]);
    lightingShader.setVec3("pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setVec3("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
    lightingShader.setVec3("pointLights[0].specular", 1.0f, 1.0f, 1.0f);
    lightingShader.setFloat("pointLights[0].constant", 1.0f);
    lightingShader.setFloat("pointLights[0].linear", 0.09f);
    lightingShader.setFloat("pointLights[0].quadratic", 0.032f);lightingShader.setVec3("pointLights[1].position", pointLightPositions[1]);
    lightingShader.setVec3("pointLights[1].ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setVec3("pointLights[1].diffuse", 0.8f, 0.8f, 0.8f);
    lightingShader.setVec3("pointLights[1].specular", 1.0f, 1.0f, 1.0f);
    lightingShader.setFloat("pointLights[1].constant", 1.0f);
    lightingShader.setFloat("pointLights[1].linear", 0.09f);
    lightingShader.setFloat("pointLights[1].quadratic", 0.032f);lightingShader.setVec3("pointLights[2].position", pointLightPositions[2]);
    lightingShader.setVec3("pointLights[2].ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setVec3("pointLights[2].diffuse", 0.8f, 0.8f, 0.8f);
    lightingShader.setVec3("pointLights[2].specular", 1.0f, 1.0f, 1.0f);
    lightingShader.setFloat("pointLights[2].constant", 1.0f);
    lightingShader.setFloat("pointLights[2].linear", 0.09f);
    lightingShader.setFloat("pointLights[2].quadratic", 0.032f);lightingShader.setVec3("pointLights[3].position", pointLightPositions[3]);
    lightingShader.setVec3("pointLights[3].ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setVec3("pointLights[3].diffuse", 0.8f, 0.8f, 0.8f);
    lightingShader.setVec3("pointLights[3].specular", 1.0f, 1.0f, 1.0f);
    lightingShader.setFloat("pointLights[3].constant", 1.0f);
    lightingShader.setFloat("pointLights[3].linear", 0.09f);
    lightingShader.setFloat("pointLights[3].quadratic", 0.032f);
    // -----------
    while (!glfwWindowShouldClose(window))
    {// view/projection transformationsglm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);glm::mat4 view = camera.GetViewMatrix();lightingShader.setMat4("projection", projection);lightingShader.setMat4("view", view);// 绑定漫反射贴图-出过错,放在绘制光源cube那里glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, texture3);glBindVertexArray(cubeVAO);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));lightingShader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);}// 绘画灯// world transformationglm::mat4 model;lightCubeShader.use();lightCubeShader.setMat4("projection", projection);lightCubeShader.setMat4("view", view);glBindVertexArray(cubeVAO);for (unsigned int i = 0; i < 4; i++) {model = glm::mat4(1.0f);model = glm::translate(model, pointLightPositions[i]);model = glm::scale(model, glm::vec3(0.2f));lightCubeShader.setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);}glfwSwapBuffers(window);glfwPollEvents();
    
  • 关键代码

    glsl

    #define NR_POINT_LIGHTS 4
    uniform PointLight pointLights[NR_POINT_LIGHTS];
    

    cpp

    lightingShader.setVec3("pointLights[1].position", pointLightPositions[1]);
    lightingShader.setVec3("pointLights[1].ambient", 0.05f, 0.05f, 0.05f);
    

没有聚光灯效果

有聚光灯效果

  • 修改代码

    glsl

    .....
    struct Material {sampler2D diffuse;  // 漫反射颜色分量从纹理采样sampler2D specular;//  镜面光照颜色分量从纹理采样sampler2D spotLightDiffuse;//  聚光灯的漫反射颜色分量从纹理采样float shininess;
    }; 
    .....
    uniform SpotLight spotLight;// 计算点光源影响当前片段的颜色
    vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir){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.0 / (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()
    {........// 点光源for(int i = 0; i < NR_POINT_LIGHTS; i++){result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);}// 聚光灯result += CalcSpotLight(spotLight, norm, FragPos, viewDir);FragColor = vec4(result, 1.0);
    }
    

    cpp

    unsigned int texture3 = loadTexture("assest/textures/spotlightimg.jpg");
    lightingShader.setInt("material.spotLightDiffuse", 2);
    // -----------
    while (!glfwWindowShouldClose(window))
    {// 聚光灯lightingShader.setVec3("spotLight.ambient", 0.1f, 0.1f, 0.1f);lightingShader.setVec3("spotLight.diffuse", 0.8f, 0.8f, 0.8f);lightingShader.setVec3("spotLight.specular", 1.0f, 1.0f, 1.0f);lightingShader.setVec3("spotLight.position", camera.Position);lightingShader.setVec3("spotLight.direction", camera.Front);// direction是光照射方向lightingShader.setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));lightingShader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(17.5f)));lightingShader.setFloat("spotLight.constant", 1.0f);lightingShader.setFloat("spotLight.linear", 0.09f);lightingShader.setFloat("spotLight.quadratic", 0.032f);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, texture3);
    
  • 效果

    请添加图片描述

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...