美文网首页
LearnOpenGL 多光源

LearnOpenGL 多光源

作者: li_礼光 | 来源:发表于2020-10-07 16:30 被阅读0次

    我们在前面的教程中已经学习了许多关于OpenGL 光照的知识,其中包括冯氏照明模型(Phong shading)、光照材质(Materials)、光照图(Lighting maps)以及各种投光物(Light casters)。本教程将结合上述所学的知识,创建一个包含六个光源的场景。我们将模拟一个类似阳光的平行光(Directional light)和4个定点光(Point lights)以及一个手电筒(Flashlight).

    要在场景中使用多光源我们需要封装一些GLSL函数用来计算光照。如果我们对每个光源都去写一遍光照计算的代码,这将是一件令人恶心的事情,并且这些放在main函数中的代码将难以理解,所以我们将一些操作封装为函数。

    GLSL中的函数与C语言的非常相似,它需要一个函数名、一个返回值类型。并且在调用前必须提前声明。接下来我们将为下面的每一种光照来写一个函数。

    当我们在场景中使用多个光源时一般使用以下途径:创建一个代表输出颜色的向量。每一个光源都对输出颜色贡献一些颜色。因此,场景中的每个光源将进行独立运算,并且运算结果都对最终的输出颜色有一定影响。下面是使用这种方式进行多光源运算的一般结构:

    out vec4 color;
    
    void main()
    {
      // 定义输出颜色
      vec3 output;
      // 将平行光的运算结果颜色添加到输出颜色
      output += someFunctionToCalculateDirectionalLight();
      // 同样,将定点光的运算结果颜色添加到输出颜色
      for(int i = 0; i < nr_of_point_lights; i++)
        output += someFunctionToCalculatePointLight();
      // 添加其他光源的计算结果颜色(如投射光)
      output += someFunctionToCalculateSpotLight();
    
      color = vec4(output, 1.0);
    }  
    


    实践

    Shader

    #define STRINGIZE(x) #x
    #define SHADER(shader) STRINGIZE(shader)
    
    //顶点着色器程序
    static char *myMyMultipleLightSourcesVertexShaderStr = SHADER(
        \#version 330 core\n
                                                 
        layout (location = 0) in vec3 position; //顶点数据源输入
        layout (location = 1) in vec3 normal; //法向量
        layout (location = 2) in vec2 texCoords; //纹理数据源输入(2D)
    
        uniform mat4 myProjection;//投影矩阵
        uniform mat4 myView;//观察矩阵
        uniform mat4 myModel;//模型矩阵
                                                 
        out vec3 Normal;//法线向量
        out vec3 FragPos;//片段位置
        out vec2 TexCoords;//把片元着色器的纹理从这里输出
    
        void main()
        {
            gl_Position = myProjection * myView * myModel * vec4(position, 1.0f);
            Normal = normal;
            FragPos = vec3(myModel * vec4(position, 1.0f) );
            TexCoords = texCoords;
        }
    );
    
    
    
    //片元着色器程序
    static char *myMyMultipleLightSourcesFragmentShaderSrc = SHADER(
        \#version 330 core\n
        //材质
        struct Material {
            sampler2D diffuse;
            sampler2D specular;
            float shininess;//镜面反射散射因子(半径).
        };
    
        //定向光源
        struct DirLight {
            vec3 direction;//光源方向
            vec3 ambient;//环境光照
            vec3 diffuse;//漫反射光照
            vec3 specular;//镜面反射光照
        };
                                                                    
        //点光源
        struct PointLight {
            vec3 position;//光源位置
    
            float constant; //常量
            float linear;//一次项
            float quadratic;//二次项
            
            vec3 ambient;//环境光照
            vec3 diffuse;//漫反射光照
            vec3 specular;//镜面反射光照
        };
    
        #define NR_POINT_LIGHTS 4
                                                                    
        in vec3 Normal;
        in vec3 FragPos;
        in vec2 TexCoords;
                                                          
        uniform vec3 viewPos;
        uniform Material material;//材质
        uniform DirLight dirLight;
        uniform PointLight pointLights[NR_POINT_LIGHTS];
    
        out vec4 color;
                                                                    
        vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);//定向光照颜色
        vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);//点光源颜色
    
        void main()
        {
            // Properties
            vec3 norm = normalize(Normal);
            vec3 viewDir = normalize(viewPos - FragPos);
            
            // == ======================================
            //我们的照明分为3个阶段:定向,点光源和可选的手电筒,对于每个阶段,都定义了一个计算功能,用于计算每个灯的相应颜色。
            //在main()函数中,我们获取所有计算出的颜色,并将其求和为该片段的最终颜色。
            // == ======================================
        
            // Phase 1: 定向光源
            vec3 result = CalcDirLight(dirLight, norm, viewDir);
        
            // Phase 2: 计算点光源
            for(int i = 0; i < NR_POINT_LIGHTS; i++)
                result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
        
            // Phase 3: 聚光
            // result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
            
            color = vec4(result, 1.0);
        }
                                                                    
                                                                    
        // 使用定向光时计算颜色。
        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.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);
        }
                                                                    
    );
    

    顶点数据

    GLfloat myMultipleLightSourcesVertices[] = {
        //顶点数据              法线                  纹理坐标
       -0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f,
        0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   1.0f, 1.0f,
       -0.5f,  0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   0.0f, 1.0f,
       -0.5f, -0.5f, -0.5f,   0.0f,  0.0f, -1.0f,   0.0f, 0.0f,
    
       -0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f,
        0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   1.0f, 1.0f,
       -0.5f,  0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   0.0f, 1.0f,
       -0.5f, -0.5f,  0.5f,   0.0f,  0.0f,  1.0f,   0.0f, 0.0f,
    
       -0.5f,  0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
       -0.5f,  0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
       -0.5f, -0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
       -0.5f, -0.5f, -0.5f,  -1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
       -0.5f, -0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
       -0.5f,  0.5f,  0.5f,  -1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
    
        0.5f,  0.5f,  0.5f,   1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
        0.5f,  0.5f, -0.5f,   1.0f,  0.0f,  0.0f,   1.0f, 0.0f,
        0.5f, -0.5f, -0.5f,   1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,   1.0f,  0.0f,  0.0f,   1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,   1.0f,  0.0f,  0.0f,   0.0f, 1.0f,
        0.5f,  0.5f,  0.5f,   1.0f,  0.0f,  0.0f,   0.0f, 0.0f,
    
       -0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,   0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,   1.0f, 0.0f,
        0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,   1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,   1.0f, 1.0f,
       -0.5f, -0.5f,  0.5f,   0.0f, -1.0f,  0.0f,   0.0f, 1.0f,
       -0.5f, -0.5f, -0.5f,   0.0f, -1.0f,  0.0f,   0.0f, 0.0f,
    
       -0.5f,  0.5f, -0.5f,   0.0f,  1.0f,  0.0f,   0.0f, 0.0f,
        0.5f,  0.5f, -0.5f,   0.0f,  1.0f,  0.0f,   1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,   0.0f,  1.0f,  0.0f,   1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,   0.0f,  1.0f,  0.0f,   1.0f, 1.0f,
       -0.5f,  0.5f,  0.5f,   0.0f,  1.0f,  0.0f,   0.0f, 1.0f,
       -0.5f,  0.5f, -0.5f,   0.0f,  1.0f,  0.0f,   0.0f, 0.0f,
    };
    

    程序

    #include <iostream>
    #include "MyMultipleLightSources.hpp"
    #include "MyProgram.hpp"
    #include "MyMultipleLightSourcesShader.h"
    #include "MyMultipleLightSourcesVertices.h"
    #include "glm.hpp"
    #include "matrix_transform.hpp"
    #include "type_ptr.hpp"
    #include "MyCamera.h"
    
    #define STB_IMAGE_IMPLEMENTATION
    #define STB_IMAGE_STATIC
    #include "stb_image.h"
    
    namespace MyMultipleLightSources {
    // Function prototypes
        void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
        void mouse_callback(GLFWwindow* window, double xpos, double ypos);
        void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
        void do_movement();
    
        // Window dimensions
        const GLuint WIDTH = 800, HEIGHT = 600;
    
        // Camera
        Camera  camera(glm::vec3(0.0f, 0.0f, 3.0f));
        GLfloat lastX  =  WIDTH  / 2.0;
        GLfloat lastY  =  HEIGHT / 2.0;
        bool    keys[1024];
    
        // Light attributes
        glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
    
        // Deltatime
        GLfloat deltaTime = 0.05f;    // Time between current frame and last frame
        GLfloat lastFrame = 0.05f;      // Time of last frame
    
    
        // Is called whenever a key is pressed/released via GLFW
        void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
        {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
                glfwSetWindowShouldClose(window, GL_TRUE);
            if (key >= 0 && key < 1024)
            {
                if (action == GLFW_PRESS)
                    keys[key] = true;
                else if (action == GLFW_RELEASE)
                    keys[key] = false;
            }
        }
    
        void do_movement()
        {
            // Camera controls
            if (keys[GLFW_KEY_W])
                camera.ProcessKeyboard(FORWARD, deltaTime);
            if (keys[GLFW_KEY_S])
                camera.ProcessKeyboard(BACKWARD, deltaTime);
            if (keys[GLFW_KEY_A])
                camera.ProcessKeyboard(LEFT, deltaTime);
            if (keys[GLFW_KEY_D])
                camera.ProcessKeyboard(RIGHT, deltaTime);
        }
    
        bool firstMouse = true;
        void mouse_callback(GLFWwindow* window, double xpos, double ypos)
        {
            if (firstMouse)
            {
                lastX = xpos;
                lastY = ypos;
                firstMouse = false;
            }
    
            GLfloat xoffset = xpos - lastX;
            GLfloat yoffset = lastY - ypos;  // Reversed since y-coordinates go from bottom to left
    
            lastX = xpos;
            lastY = ypos;
    
            camera.ProcessMouseMovement(xoffset, yoffset);
        }
    
        void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
        {
            camera.ProcessMouseScroll(yoffset);
        }
    
    
        int runMyMultipleLightSourcesCube() {
            int result = glfwInit();
            if (result == GL_FALSE) {
                printf("glfwInit 初始化失败");
                return -1;
            }
            
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
            GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "My Opengl Window", NULL, NULL);
            if(!window) {
                printf("window 创建失败");
            }
            glfwMakeContextCurrent(window);
            gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    
            
            //设置(键盘鼠标)输入事件
            //此函数设置指定窗口的按键回调,当按下,重复或释放按键时调用该回调。
            glfwSetKeyCallback(window, key_callback);
            
            //此函数设置指定窗口的光标位置回调,在移动光标时调用该回调。 回调提供了相对于窗口内容区域左上角的屏幕坐标位置。
            glfwSetCursorPosCallback(window, mouse_callback);
    
            //此函数设置指定窗口的滚动回调,在使用滚动设备(例如鼠标滚轮或触摸板的滚动区域)时调用此回调。
            //滚动回调接收所有滚动输入,例如来自鼠标滚轮或触摸板滚动区域的滚动输入。
            glfwSetScrollCallback(window, scroll_callback);
    
            //glfwSetInputMode
            //光标模式值 : GLFW_CURSOR_DISABLED
            //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            
            //切换为纹理着色器程序
            MyProgram myProgram = MyProgram(myMyMultipleLightSourcesVertexShaderStr, myMyMultipleLightSourcesFragmentShaderSrc);
    
            ///
            GLuint VBO , VAO ;
            unsigned int squareIndicesCount = 0;
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glBindVertexArray(VAO);
    
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(myMultipleLightSourcesVertices), myMultipleLightSourcesVertices, GL_STATIC_DRAW);
            
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(0 * sizeof(GLfloat)));
            glEnableVertexAttribArray(0);
    
            //法线
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
            glEnableVertexAttribArray(1);
            
            //纹理
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
            glEnableVertexAttribArray(2);
    
            //解绑VAO
            glBindVertexArray(0);
            squareIndicesCount = sizeof(myMultipleLightSourcesVertices)/(sizeof(myMultipleLightSourcesVertices[0]) * 8);
    
            glEnable(GL_DEPTH_TEST);
            
    
            //加载纹理
            unsigned int diffuseCasters_texture;
            unsigned char *diffuseCasters_data;
            int diffuseCasters_width, diffuseCasters_height, diffuseCasters_nrChannels;
            glGenTextures(1, &diffuseCasters_texture);
            glBindTexture(GL_TEXTURE_2D, diffuseCasters_texture);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            diffuseCasters_data = stbi_load( "/Users/liliguang/Desktop/LearnOpengl/LearnOpenGl/LearnOpenGl/Demo/Common/ImgSources/box.png" , &diffuseCasters_width, &diffuseCasters_height, &diffuseCasters_nrChannels, 0);
            if (diffuseCasters_data)
            {
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, diffuseCasters_width, diffuseCasters_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, diffuseCasters_data);
                glGenerateMipmap(GL_TEXTURE_2D);
                glBindTexture(GL_TEXTURE_2D, 0);
            }
            else
            {
                std::cout << "Failed to load texture" << std::endl;
            }
            stbi_image_free(diffuseCasters_data);
            
            
            unsigned int specularCasters_texture;
            unsigned char *specularCasters_data;
            int specularCasters_width, specularCasters_height, specularCasters_nrChannels;
            glGenTextures(1, &specularCasters_texture);
            glBindTexture(GL_TEXTURE_2D, specularCasters_texture);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            specularCasters_data = stbi_load( "/Users/liliguang/Desktop/LearnOpengl/LearnOpenGl/LearnOpenGl/Demo/Common/ImgSources/box_specular.png" , &specularCasters_width, &specularCasters_height, &specularCasters_nrChannels, 0);
            if (specularCasters_data)
            {
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, specularCasters_width, specularCasters_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, specularCasters_data);
                glGenerateMipmap(GL_TEXTURE_2D);
                glBindTexture(GL_TEXTURE_2D, 0);
            }
            else
            {
                std::cout << "Failed to load texture" << std::endl;
            }
            stbi_image_free(specularCasters_data);
            
            //材质-光照贴图
            glUseProgram(myProgram.program);
    
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, diffuseCasters_texture);
            glUniform1i(glGetUniformLocation(myProgram.program, "material.diffuse"), 0);//环境贴图
            
            glActiveTexture(GL_TEXTURE1);
            glBindTexture(GL_TEXTURE_2D, specularCasters_texture);
            glUniform1i(glGetUniformLocation(myProgram.program, "material.specular"), 1);//环境贴图
    
            //Cube位置
            glm::vec3 cubePositions[] = {
                glm::vec3( 0.0f,  0.0f,  0.0f),
                glm::vec3( 2.0f, -1.0f, -1.0f),
                glm::vec3(-1.5f, -2.2f, -2.5f),
                glm::vec3(-2.8f, -1.0f, -2.3f),
                glm::vec3( 2.4f, -0.4f, -3.5f),
                glm::vec3(-1.7f,  2.0f, -0.1f),
                glm::vec3( 1.3f, -2.0f, -2.2f),
                glm::vec3( 1.5f,  2.0f, -2.9f),
                glm::vec3( 1.5f,  0.2f, -1.5f),
                glm::vec3(-1.3f,  1.0f, -1.2f)
            };
            int cubePositionsCount = sizeof(cubePositions)/(sizeof(cubePositions[0]));
    
            //点光源位置
            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)
            };
            
            
            //进行绘制
            while(!glfwWindowShouldClose(window)){
                glfwPollEvents();
                do_movement();
    
                glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                
                //================================================
                glm::mat4 model = glm::mat4(1.0f);
                glm::mat4 view = glm::mat4(1.0f);
                glm::mat4 projection = glm::mat4(1.0f);
                
                GLint myModelLoc = glGetUniformLocation(myProgram.program,"myModel");
                GLint myViewLoc = glGetUniformLocation(myProgram.program,"myView");
                GLint myProjectionLoc = glGetUniformLocation(myProgram.program,"myProjection");
                
                projection = glm::perspective(glm::radians(90.0f), 1.0f, 0.01f, 100.f);//投影矩阵
                glUniformMatrix4fv(myProjectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
                
                view = camera.GetViewMatrix();
                glUniform3f(myViewLoc,  camera.Position.x, camera.Position.y, camera.Position.z);
                glUniformMatrix4fv(myViewLoc, 1, GL_FALSE, glm::value_ptr(view));
                glBindVertexArray(VAO);
                //================================================
    
                
                
                //光照
                //================================================
                //镜面反射半径
                GLint matShineLoc = glGetUniformLocation(myProgram.program, "material.shininess");
                glUniform1f(matShineLoc, 64.0f);
                GLint viewPosLoc  = glGetUniformLocation(myProgram.program, "viewPos");
                glUniform3f(viewPosLoc,  camera.Position.x, camera.Position.y, camera.Position.z);
    
                // 定向光源
                glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.direction"), -0.2f, -1.0f, -0.3f);
                glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
                glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
                glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.specular"), 0.5f, 0.5f, 0.5f);
                
                // 点光源 1 红色
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].ambient"), 1.0f, 0.0f, 0.0f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].diffuse"), 0.8f, 0.8f, 0.8f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].constant"), 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].linear"), 0.09);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].quadratic"), 0.032);
                // 点光源 2  绿色
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].ambient"), 0.0f, 1.0f, 0.0f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].diffuse"), 0.8f, 0.8f, 0.8f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].constant"), 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].linear"), 0.09);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].quadratic"), 0.032);
                // 点光源 3 蓝色
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].ambient"), 0.0f, 0.0f, 1.0f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].diffuse"), 0.8f, 0.8f, 0.8f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].specular"), 1.0f, 1.0f, 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].constant"), 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].linear"), 0.09);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].quadratic"), 0.032);
                // 点光源 4 灰
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].ambient"), 0.5f, 0.5f, 0.5f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f);
                glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].specular"), 1.0f, 1.0f, 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].constant"), 1.0f);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].linear"), 0.09);
                glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].quadratic"), 0.032);
                //================================================
    
                for(GLuint i = 0; i < cubePositionsCount; i++)
                {
                    model = glm::translate(model, cubePositions[i]);
                    GLfloat angle = 20.0f * i;
                    model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
                    glUniformMatrix4fv(myModelLoc, 1, GL_FALSE, glm::value_ptr(model));
                    glDrawArrays(GL_TRIANGLES, 0, squareIndicesCount);
                }
                
                glBindVertexArray(0);
                glfwSwapBuffers(window);
            }
    
            //程序销毁
            glfwTerminate();
            return 1;
        }
    }
    

    效果

    大概效果

    相关文章

      网友评论

          本文标题:LearnOpenGL 多光源

          本文链接:https://www.haomeiwen.com/subject/tywfpktx.html