美文网首页
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 多光源

    我们在前面的教程中已经学习了许多关于OpenGL 光照的知识,其中包括冯氏照明模型(Phong shading)、...

  • LearnOpenGL 入门篇

    官方教程 :LearnOpenGL-CN[https://learnopengl-cn.readthedocs.i...

  • OpenGL学习资料和记录

    学习资料 OpenGL: LearnOpenGL[https://learnopengl.com/] 计算机图形/...

  • HDR

    参考资料 LearnOpenGL - HDR[https://learnopengl.com/Advanced-L...

  • 实时渲染、三种渲染方法介绍

    实时渲染,一般有三种渲染方法,多光源一次渲染,多光源多次渲染和延迟着色。 多光源一次渲染:对于每个物体,计算所有光...

  • opengl相关资料

    推荐度较高的opengl教程:《learnopengl》中文版https://learnopengl-cn.git...

  • 教程

    LearnOpenGL CN

  • OpenGL学习1——OpenGL简介和环境搭建

    网址 可以从这个网站LearnOpenGL[https://learnopengl.com/]下载电子书或者直接网...

  • OpenGL学习网站收集

    LearnOpenGL CNGitHub代码

  • URP多光源处理

    URP多光源处理 该节我们将实现在URP下接收多个光照 本系列URP不再阐述具体的效果实现逻辑与公式推导,侧重于U...

网友评论

      本文标题:LearnOpenGL 多光源

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