• 多光源(定向光、点光源、聚光灯)


      前篇学习了单个的光源,现在在一个场景中放置多个不同的光源,包括一个定向光源、4个点光源、一个聚光灯。

      

      GLSL代码如下(片段着色器):

    #version 430 core
    out vec4 color;
    
    in VS_OUT{
        vec3 FragPos;
        vec3 Normal;
        vec2 TexCoords;
    }vs_in;
    
    struct Material{
        sampler2D diffuse;
        sampler2D specular;
        float shininess;
    };
    
    struct DirLight{
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    
        vec3 direction;
    };
    
    struct PointLight{
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    
        float constant;
        float linear;
        float quadratic;
        
        vec3 position;
    };
    
    struct SpotLight{
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    
        float constant;
        float linear;
        float quadratic;
        
        vec3 position;
        vec3 direction;
        float cutOff;
        float outerCutOff;
    };
    #define NR_POINT_LIGHTS 4
    uniform Material material;
    uniform DirLight dirLight;
    uniform PointLight pointLights[NR_POINT_LIGHTS];
    uniform SpotLight spotLight;
    uniform vec3 viewPos;
    
    vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
    {
        vec3 lightDir=normalize(-light.direction);
    
        vec3 ambient=light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords));
        
        float diff=max(dot(normal,lightDir),0.0f);
        vec3 diffuse=light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords));
        
        vec3 reflectDir=reflect(-lightDir,normal);
        float spec=pow(max(dot(viewDir,reflectDir),0.0f),material.shininess);
        vec3 specular=light.specular * spec * vec3(texture(material.specular, vs_in.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, vs_in.TexCoords));
        vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, vs_in.TexCoords));
        vec3 specular = light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords));
        ambient  *= attenuation;
        diffuse  *= attenuation;
        specular *= attenuation;
        return (ambient + diffuse + specular);
    }
    
    vec3 CalcSpotLight(SpotLight 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, vs_in.TexCoords));
        vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, vs_in.TexCoords));
        vec3 specular = light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords));
        //ambient  *= attenuation;
        //diffuse  *= attenuation;
        //specular *= attenuation;
    
        float theta=dot(lightDir,normalize(-light.direction));
        float epsilon=light.cutOff-light.outerCutOff;
        float intensity=clamp((theta-light.outerCutOff)/epsilon,0.0,1.0);
    
        ambient*=intensity;
        diffuse*=intensity;
        specular*=intensity;
        return (ambient + diffuse + specular);
    }
    
    
    void main()
    {
        vec3 norm=normalize(vs_in.Normal);
        vec3 viewDir=normalize(viewPos-vs_in.FragPos);
    
        //定向光
        vec3 result=CalcDirLight(dirLight, norm, viewDir);
        //点光源
        for(int i=0;i<NR_POINT_LIGHTS;i++){
            result+=CalcPointLight(pointLights[i], norm, vs_in.FragPos, viewDir);
        }
        //聚光灯
        result+=CalcSpotLight(spotLight, norm, vs_in.FragPos, viewDir);
    
        color=vec4(result,1.0f);
    }

      

      渲染代码如下:

    void SceneRendering::CubeRendering() {
        //update uniform buffer
        cube->setViewMat(phc->getViewMatrix());
        cube->setProjectionMat(phc->getProjectionMatrix());
        shader_multiLights->use();
    
        shader_multiLights->setInt("material.diffuse", 0);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, container);
        shader_multiLights->setInt("material.specular", 1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, container_specular);
        shader_multiLights->setFloat("material.shininess", 500);
        shader_multiLights->setVec3("viewPos", phc->getPos());
    
        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)
        };
        glm::vec3 pointLightColors[] = {
            glm::vec3(1.0f, 0.6f, 0.0f),
            glm::vec3(1.0f, 0.0f, 0.0f),
            glm::vec3(0.0f, 1.0, 0.0),
            glm::vec3(0.2f, 0.2f, 1.0f)
        };
        // Directional light
        shader_multiLights->setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f);
        shader_multiLights->setVec3("dirLight.ambient", 0.3f, 0.24f, 0.14f);
        shader_multiLights->setVec3("dirLight.diffuse", 0.7f, 0.42f, 0.26f);
        shader_multiLights->setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f);
        // Point light 1
        shader_multiLights->setVec3("pointLights[0].position", pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
        shader_multiLights->setVec3("pointLights[0].ambient", pointLightColors[0].x * 0.1, pointLightColors[0].y * 0.1, pointLightColors[0].z * 0.1);
        shader_multiLights->setVec3("pointLights[0].diffuse", pointLightColors[0].x, pointLightColors[0].y, pointLightColors[0].z);
        shader_multiLights->setVec3("pointLights[0].specular", pointLightColors[0].x, pointLightColors[0].y, pointLightColors[0].z);
        shader_multiLights->setFloat("pointLights[0].constant", 1.0f);
        shader_multiLights->setFloat("pointLights[0].linear", 0.09f);
        shader_multiLights->setFloat("pointLights[0].quadratic", 0.032f);
        // Point light 2
        shader_multiLights->setVec3("pointLights[1].position", pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
        shader_multiLights->setVec3("pointLights[1].ambient", pointLightColors[1].x * 0.1, pointLightColors[1].y * 0.1, pointLightColors[1].z * 0.1);
        shader_multiLights->setVec3("pointLights[1].diffuse", pointLightColors[1].x, pointLightColors[1].y, pointLightColors[1].z);
        shader_multiLights->setVec3("pointLights[1].specular", pointLightColors[1].x, pointLightColors[1].y, pointLightColors[1].z);
        shader_multiLights->setFloat("pointLights[1].constant", 1.0f);
        shader_multiLights->setFloat("pointLights[1].linear", 0.09f);
        shader_multiLights->setFloat("pointLights[1].quadratic", 0.032f);
        // Point light 3
        shader_multiLights->setVec3("pointLights[2].position", pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
        shader_multiLights->setVec3("pointLights[2].ambient", pointLightColors[2].x * 0.1, pointLightColors[2].y * 0.1, pointLightColors[2].z * 0.1);
        shader_multiLights->setVec3("pointLights[2].diffuse", pointLightColors[2].x, pointLightColors[2].y, pointLightColors[2].z);
        shader_multiLights->setVec3("pointLights[2].specular", pointLightColors[2].x, pointLightColors[2].y, pointLightColors[2].z);
        shader_multiLights->setFloat("pointLights[2].constant", 1.0f);
        shader_multiLights->setFloat("pointLights[2].linear", 0.09f);
        shader_multiLights->setFloat("pointLights[2].quadratic", 0.032f);
        // Point light 4
        shader_multiLights->setVec3("pointLights[3].position", pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
        shader_multiLights->setVec3("pointLights[3].ambient", pointLightColors[3].x * 0.1, pointLightColors[3].y * 0.1, pointLightColors[3].z * 0.1);
        shader_multiLights->setVec3("pointLights[3].diffuse", pointLightColors[3].x, pointLightColors[3].y, pointLightColors[3].z);
        shader_multiLights->setVec3("pointLights[3].specular", pointLightColors[3].x, pointLightColors[3].y, pointLightColors[3].z);
        shader_multiLights->setFloat("pointLights[3].constant", 1.0f);
        shader_multiLights->setFloat("pointLights[3].linear", 0.9f);
        shader_multiLights->setFloat("pointLights[3].quadratic", 0.032f);
        // Spot light
        shader_multiLights->setVec3("spotLight.position", phc->getPos());
        shader_multiLights->setVec3("spotLight.direction", phc->GetForwardVec());
        shader_multiLights->setVec3("spotLight.ambient", 0.0f, 0.0f, 0.0f);
        shader_multiLights->setVec3("spotLight.diffuse", 1.0f, 1.0f, 0.0f);
        shader_multiLights->setVec3("spotLight.specular", 1.0f, 1.0f, 0.0f);
        shader_multiLights->setFloat("spotLight.constant", 1.0f);
        shader_multiLights->setFloat("spotLight.linear", 0.9f);
        shader_multiLights->setFloat("spotLight.quadratic", 0.032f);
        shader_multiLights->setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
        shader_multiLights->setFloat("spotLight.outerCutOff", glm::cos(glm::radians(14.5f)));
    
    
        // draw cubes
        for (unsigned int i = 0; i < 10; i++)
        {
            glm::mat4 model;
            model = glm::scale(model, glm::vec3(5));
            model = glm::translate(model, cube->cubePositions[i]);
            float angle = 20.0f * i;
            model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
            shader_multiLights->setMat4("model", model);
            cube->DrawCube();
        }
    }

      

      效果图:

      1、定向光+点光源

      

      2、定向光+点光源+聚光灯(软影)

      

      

      

  • 相关阅读:
    使用Azure进行自动化机器学习
    关于ML.NET v1.0 RC的发布说明
    关于ML.NET v0.8的发布说明
    使用ML.NET + Azure DevOps + Azure Container Instances打造机器学习生产化
    使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型
    neo4j 数据库迁移
    ubuntu1604 搜狗输入法安装
    Chrome 键盘快捷键
    Ubuntu Cleaner清理工具
    bash 数组
  • 原文地址:https://www.cnblogs.com/chen9510/p/11625464.html
Copyright © 2020-2023  润新知