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);
    
  • 效果

    请添加图片描述

相关内容

热门资讯

关于蜜蜂的作文四年级【优选6... 关于蜜蜂的作文四年级 篇一蜜蜂是一种非常有趣的昆虫,它们生活在蜂巢中,有着重要的作用。今天,我就来给...
关于危急时刻的四年级作文50... 关于危急时刻的四年级作文500字 篇一危急时刻在我们的生活中,我们常常会遇到一些危急时刻,这些时刻需...
我最敬佩的一位名人四年级作文... 我最敬佩的一位名人四年级作文 篇一我最敬佩的一位名人是李彦宏。李彦宏是中国著名的企业家,同时也是百度...
感恩老师四年级作文600字【... 篇一:感恩老师的温暖我是一名四年级的学生,今天我要写一篇关于感恩老师的作文。老师是我们成长道路上最重...
做家务的作文400字四年级作... 做家务的作文400字四年级作文20篇篇一:我喜欢做家务我是一个四年级的小学生,我喜欢做家务。每天放学...
四年级写作文买菜400字(经... 四年级写作文买菜400字 篇一:去菜市场买菜四年级的我,有一次和妈妈一起去菜市场买菜,这是我第一次亲...
四年级下册数学暑假新时空答案... 四年级下册数学暑假新时空答案 篇一在四年级下册的数学学习中,我们将继续探索数学的奥秘和应用。而暑假正...
地雷花四年级作文【最新3篇】 地雷花四年级作文 篇一地雷花地雷花是一种奇特的植物,它的花朵看起来像一颗小小的地雷。我在学校的花坛里...
我和孙悟空的一天四年级上册作... 我和孙悟空的一天四年级上册作文 篇一今天是一个特殊的日子,我竟然和孙悟空一起度过了一天!早上,我醒来...
推荐一个好地方作文四年级45... 推荐一个好地方作文四年级450字 篇一我的家乡是一个非常美丽的地方,我推荐大家来参观一下。我家乡的风...
小学的小学四年级作文500字... 小学的小学四年级作文500字 篇一我喜欢的运动我是一个活泼好动的小女孩,喜欢参加各种运动。今天我就来...
今天我当家四年级作文(推荐6... 今天我当家四年级作文 篇一我当家的一天今天,我得到了一个特殊的任务,那就是要当家一天。这是我第一次担...
跳绳比赛四年级作文(通用6篇... 跳绳比赛四年级作文 篇一跳绳比赛的经历我是一名四年级的学生,最近我们学校举办了一场跳绳比赛。这是我第...
家乡变化作文400字四年级(... 家乡变化作文400字四年级 篇一家乡变化我爱我的家乡,那是一个美丽而又宁静的地方。然而,自从几年前,...
一件高兴的事250作文四年级... 篇一:一件高兴的事今天,我要给大家讲一个让我非常高兴的事情。那天,我和妈妈一起去超市买东西。在超市里...
四年级写大自然的景色作文30... 四年级写大自然的景色作文300字 篇一大自然的美景大自然是我们共同的母亲,给予我们无尽的美景和宝贵的...
小小动物园四年级作文【精简6... 小小动物园四年级作文 篇一我参观了一个小小的动物园,里面有许多有趣的动物。首先,我看到了一只可爱的小...
小小动物园四年级作文(精简6... 小小动物园四年级作文 篇一我参观了一个小小的动物园,这是我第一次看到这么多不同种类的动物。动物园里有...
悔恨400字作文【实用3篇】 悔恨400字作文 篇一悔恨是一种深深的内心痛苦,当我们回首往事,发现自己的错误和过失时,心中不禁涌起...
我的奇思妙想四年级作文350... 我的奇思妙想四年级作文350字 篇一我曾经有一个奇思妙想,那就是创造一个可以让人们实现任何愿望的神奇...