当前位置: 首页 > news >正文

OpenGL学习日记之光照计算

引言

现实生活中的光照极其复杂,而且会收到很多因素的影响,是我们当前计算机的算力无法模拟的。因此我们会根据一些简化的模型来模拟现实光照,这样在可以模拟出近似的光照感受,但是又没有那么复杂的计算。
常用的光照模型有:兰伯特光照模型(主要是模拟漫反射),半兰伯特光照模型(调优兰伯特全黑的缺点),Phong光照模型(模拟镜面反射),BlinnPhong光照模型(兰伯特+Phong)等

Phong光照模型

从模拟光照的角度,我们主要有3种光照:环境光、漫反射光照、镜面反射

环境光
现实生活中,光照通常来自于多个光源,并且会在多个物体之间发散和反弹,一个物体的光照可能受到来自一个非直射的光源影响,最后才进入人眼,也就是所谓的间接光照。考虑到这种情况的算法叫做全局照明(Global Illumination)算法,但是这种算法既开销高昂又极其复杂。
所以我们将会使用一种简化的全局照明模型,叫做环境光照(Ambient Lighting)。我们使用一个很小的常量(光)颜色添加进物体片段的最终颜色里,这看起来就像即使没有直射光源也始终存在着一些发散的光。

漫反射光
光线照在粗糙物体表面,随机散射到各个方向,漫反射中视角的位置是不重要的,因为反射是完全随机的,所以在任何反射方向都是随机的。我们需要测量这个光线与它所接触片段之间的角度。如果光线垂直于物体表面,这束光对物体的影响会最大。

镜面反射
是光线经过物体表面,反射到视野中,当反射光线与人的眼睛看得方向平行时,强度最大,高光效果最明显,夹角为90度时,强度最小。

光源类型

定向光(平行光)

当一个光源很远的时候,来自光源的每条光线接近于平行。这看起来就像所有的光线来自于同一个方向,无论物体和观察者在哪儿。当一个光源被设置为无限远时,它被称为定向光(Directional Light),因为所有的光线都有着同一个方向;它会独立于光源的位置。
我们知道的定向光源的一个好例子是,太阳。太阳和我们不是无限远,但它也足够远了,在计算光照的时候,我们感觉它就像无限远。在下面的图片里,来自于太阳的所有的光线都被定义为平行光,如下图所示:

在这里插入图片描述

点光源

某一个位置发出的光源,并且该光照强度会根据距离该光源的位置发生变化,距离光源位置越远,光照越弱,光照会随着距离发生衰减。衰减如下图所示

在这里插入图片描述

聚光灯

聚光是一种位于环境中某处的光源,它不是向所有方向照射,而是只朝某个方向照射。结果是只有一个聚光照射方向的确定半径内的物体才会被照亮,其他的都保持黑暗。
聚光的好例子是路灯或手电筒,OpenGL中的聚光用世界空间位置,一个方向和一个指定了聚光半径的切光角来表示。我们计算的每个片段,如果片段在聚光的切光方向之间(就是在圆锥体内),我们就会把片段照亮。如下图所示:

在这里插入图片描述

Phong光照模型GLSL代码

顶点着色器代码

脚本:VertexShaderSource2_1_1.txt

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords;out vec3 Normal;
out vec3 FragPos;
out vec2 TexCoords;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main()
{gl_Position = projection * view *  model * vec4(position, 1.0f);FragPos = vec3(model * vec4(position, 1.0f));Normal = mat3(transpose(inverse(model))) * normal;  TexCoords=texCoords;
}

片段着色器代码

脚本:FragmentShaderSource2_1_1.txt

#version 330 core
out vec4 color;//片段UV坐标
in vec2 TexCoords;
//片段世界空间位置坐标
in vec3 FragPos;  
//片段世界空间法线
in vec3 Normal; struct Material
{vec3 ambient;//漫反射贴图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;
};//聚光灯封装结构体
struct SpotLight {vec3 ambient;vec3 diffuse;vec3 specular;//衰减参数float constant;float linear;float quadratic;vec3 position;vec3 direction;//内部切光角float cutOff;//外部切光角float outerCutOff;
};//观察者位置坐标
uniform vec3 viewPos;
uniform Material material;uniform DirLight dirLight;
uniform SpotLight spotLight;
#define NR_POINT_LIGHTS 4  
uniform PointLight pointLights[NR_POINT_LIGHTS];vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 noraml, vec3 fragPos, vec3 viewDir);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);// 第三部,计算聚光灯光照//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.0f), 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(lightDir,normal),0.0f);vec3 reflectDir=reflect(-lightDir,normal);float spec=pow(max(dot(viewDir,reflectDir),0.0f),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);
}vec3 CalcSpotLight(SpotLight light, vec3 noraml, vec3 fragPos, vec3 viewDir)
{vec3 lightDir=normalize(light.position-fragPos);float theta = dot(lightDir, normalize(-light.direction));float epsilon = light.cutOff - light.outerCutOff;float intensity = clamp((theta - light.outerCutOff) / epsilon,0.0, 1.0);float diff=max(dot(lightDir,noraml),0.0f);vec3 reflectDir=reflect(-lightDir,noraml);float spec=pow(max(dot(viewDir,reflectDir),0.0f),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;diffuse  *= intensity;specular *= intensity;return (ambient + diffuse + specular);
}

渲染流程代码

GLSL渲染代码

#include <iostream>
#include <cmath>// GLEW
#define GLEW_STATIC
#include <GL/glew.h>// GLFW
#include <GLFW/glfw3.h>// Other Libs
#include <SOIL.h>
// GLM Mathematics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>// Other includes
#include "Shader.h"// 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
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
GLfloat yaw = -90.0f;	// Yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right (due to how Eular angles work) so we initially rotate a bit to the left.
GLfloat pitch = 0.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.0f;	// Time between current frame and last frame
GLfloat lastFrame = 0.0f;  	// Time of last frame// The MAIN function, from here we start the application and run the game loop
int main()
{// Init GLFWglfwInit();// Set all the required options for GLFWglfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);// Create a GLFWwindow object that we can use for GLFW's functionsGLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);glfwMakeContextCurrent(window);// Set the required callback functionsglfwSetKeyCallback(window, key_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);// GLFW OptionsglfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensionsglewExperimental = GL_TRUE;// Initialize GLEW to setup the OpenGL Function pointersglewInit();// Define the viewport dimensionsglViewport(0, 0, WIDTH, HEIGHT);// OpenGL optionsglEnable(GL_DEPTH_TEST);// Build and compile our shader programShader lightingShader("VertexShaderSource2_1_1.txt", "FragmentShaderSource2_1_1.txt");Shader lampShader("VertexShaderSource1_7_1.txt", "FragmentShaderSource1_7_1.txt");// Set up vertex data (and buffer(s)) and attribute pointers// Set up vertex data (and buffer(s)) and attribute pointersGLfloat vertices[] = {// Positions          // Normals           // Texture Coords-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,  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,  0.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,  1.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,  0.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,  1.0f,  0.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,  1.0f,  1.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,  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,  0.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,  1.0f,  1.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,  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,  0.0f,  1.0f};// Positions all containersglm::vec3 cubePositions[] = {glm::vec3(0.0f,  0.0f,  0.0f),glm::vec3(2.0f,  5.0f, -15.0f),glm::vec3(-1.5f, -2.2f, -2.5f),glm::vec3(-3.8f, -2.0f, -12.3f),glm::vec3(2.4f, -0.4f, -3.5f),glm::vec3(-1.7f,  3.0f, -7.5f),glm::vec3(1.3f, -2.0f, -2.5f),glm::vec3(1.5f,  2.0f, -2.5f),glm::vec3(1.5f,  0.2f, -1.5f),glm::vec3(-1.3f,  1.0f, -1.5f)};// Positions of the point lightsglm::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)};// First, set the container's VAO (and VBO)GLuint VBO, containerVAO;glGenVertexArrays(1, &containerVAO);glGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindVertexArray(containerVAO);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);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);glBindVertexArray(0);// Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))GLuint lightVAO;glGenVertexArrays(1, &lightVAO);glBindVertexArray(lightVAO);// We only need to bind to the VBO (to link it with glVertexAttribPointer), no need to fill it; the VBO's data already contains all we need.glBindBuffer(GL_ARRAY_BUFFER, VBO);// Set the vertex attributes (only position data for the lamp))glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the other data in our buffer object (we don't need the normals/textures, only positions).glEnableVertexAttribArray(0);glBindVertexArray(0);// Load texturesGLuint diffuseMap;glGenTextures(1, &diffuseMap);int width, height;unsigned char* image;// Diffuse mapimage = SOIL_load_image("container2.png", &width, &height, 0, SOIL_LOAD_RGB);glBindTexture(GL_TEXTURE_2D, diffuseMap);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);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_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);GLuint specularMap;glGenTextures(1, &specularMap);image = SOIL_load_image("container2_specular.png", &width, &height, 0, SOIL_LOAD_RGB);glBindTexture(GL_TEXTURE_2D, specularMap);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);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_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);glBindTexture(GL_TEXTURE_2D, 0);lightingShader.Use();glUniform1i(glGetUniformLocation(lightingShader.Program, "material.diffuse"), 0);glUniform1i(glGetUniformLocation(lightingShader.Program, "material.specular"), 1);// Game loopwhile (!glfwWindowShouldClose(window)){// Calculate deltatime of current frameGLfloat currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functionsglfwPollEvents();do_movement();// Clear the colorbufferglClearColor(0.1f, 0.1f, 0.1f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Use cooresponding shader when setting uniforms/drawing objectslightingShader.Use();    glUniform3f(glGetUniformLocation(lightingShader.Program, "viewPos"), cameraPos.x, cameraPos.y, cameraPos.z);glUniform1f(glGetUniformLocation(lightingShader.Program, "material.shininess"), 64.0f);     glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.direction"), -0.2f, -1.0f, -0.3f);glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.ambient"), 0.05f, 0.05f, 0.05f);glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);glUniform3f(glGetUniformLocation(lightingShader.Program, "dirLight.specular"), 0.5f, 0.5f, 0.5f);// Point light 1glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].diffuse"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].constant"), 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].linear"), 0.09f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[0].quadratic"), 0.032f);// Point light 2glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].diffuse"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].constant"), 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].linear"), 0.09f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[1].quadratic"), 0.032f);// Point light 3glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].ambient"), 0.05f, 0.05f, 0.05f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].diffuse"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[2].specular"), 1.0f, 1.0f, 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].constant"), 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].linear"), 0.09f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[2].quadratic"), 0.032f);// Point light 4glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].ambient"), 0.05f, 0.05f, 0.05f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "pointLights[3].specular"), 1.0f, 1.0f, 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].constant"), 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].linear"), 0.09f);glUniform1f(glGetUniformLocation(lightingShader.Program, "pointLights[3].quadratic"), 0.032f);glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.ambient"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.diffuse"), 0.8f, 0.8f, 0.8f);glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.specular"), 1.0f, 1.0f, 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.constant"), 1.0f);glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.linear"), 0.09);glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.quadratic"), 0.032);glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.position"), cameraPos.x, cameraPos.y, cameraPos.z);glUniform3f(glGetUniformLocation(lightingShader.Program, "spotLight.direction"), cameraFront.x, cameraFront.y, cameraFront.z);glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.cutOff"), glm::cos(glm::radians(12.5f)));glUniform1f(glGetUniformLocation(lightingShader.Program, "spotLight.outerCutOff"), glm::cos(glm::radians(17.5f)));// Create camera transformationsglm::mat4 view(1);glm::mat4 model(1);glm::mat4 projection(1);     view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);projection = glm::perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);// Get the uniform locationsGLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");GLint viewLoc = glGetUniformLocation(lightingShader.Program, "view");GLint projLoc = glGetUniformLocation(lightingShader.Program, "projection");// Pass the matrices to the        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));// Bind diffuse mapglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, diffuseMap);// Bind specular mapglActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, specularMap);// Draw the container (using container's vertex attributes)glBindVertexArray(containerVAO);for (GLuint i = 0; i < 10; i++){model = glm::mat4(1);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(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glDrawArrays(GL_TRIANGLES, 0, 36);}glBindVertexArray(0);  lampShader.Use();// Get location objects for the matrices on the lamp shader (these could be different on a different shader)modelLoc = glGetUniformLocation(lampShader.Program, "model");viewLoc = glGetUniformLocation(lampShader.Program, "view");projLoc = glGetUniformLocation(lampShader.Program, "projection");// Set matricesglUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));// We now draw as many light bulbs as we have point lights.glBindVertexArray(lightVAO);for (GLuint i = 0; i < 4; i++){model = glm::mat4(1);model = glm::translate(model, pointLightPositions[i]);model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cubeglUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));glDrawArrays(GL_TRIANGLES, 0, 36);}glBindVertexArray(0);// Swap the screen buffersglfwSwapBuffers(window);}// Terminate GLFW, clearing any resources allocated by GLFW.glfwTerminate();return 0;
}// 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 controlsGLfloat cameraSpeed = 5.0f * deltaTime;if (keys[GLFW_KEY_W])cameraPos += cameraSpeed * cameraFront;if (keys[GLFW_KEY_S])cameraPos -= cameraSpeed * cameraFront;if (keys[GLFW_KEY_A])cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;if (keys[GLFW_KEY_D])cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}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 leftlastX = xpos;lastY = ypos;GLfloat sensitivity = 0.05;	// Change this value to your likingxoffset *= sensitivity;yoffset *= sensitivity;yaw += xoffset;pitch += yoffset;// Make sure that when pitch is out of bounds, screen doesn't get flippedif (pitch > 89.0f)pitch = 89.0f;if (pitch < -89.0f)pitch = -89.0f;glm::vec3 front;front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));front.y = sin(glm::radians(pitch));front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));cameraFront = glm::normalize(front);}void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{}

参考链接:https://www.yumefx.com/?p=3006
参考链接:https://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/06%20Multiple%20lights/

相关文章:

OpenGL学习日记之光照计算

引言 现实生活中的光照极其复杂&#xff0c;而且会收到很多因素的影响&#xff0c;是我们当前计算机的算力无法模拟的。因此我们会根据一些简化的模型来模拟现实光照&#xff0c;这样在可以模拟出近似的光照感受&#xff0c;但是又没有那么复杂的计算。 常用的光照模型有&…...

七大排序经典排序算法

吾日三省吾身&#xff1a;高否&#xff1f;富否&#xff1f;帅否&#xff1f;答曰&#xff1a;否。滚去学习!!!(看完这篇文章先)目前只有C和C的功底&#xff0c;暂时还未开启新语言的学习&#xff0c;但是大同小异&#xff0c;语法都差不多。目录&#xff1a;一.排序定义二.排序…...

设计模式—“对象性能”

面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。 典型模式有:Singleton、Flyweight 一、Flyweight 运用共享技术将大量细粒度的对象进项复用,…...

基于Spring Boot的零食商店

文章目录项目介绍主要功能截图&#xff1a;登录后台首页个人信息管理用户管理前台首页购物车部分代码展示设计总结项目获取方式&#x1f345; 作者主页&#xff1a;Java韩立 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关…...

Python语言的优缺点

为初学者而著&#xff01;适合准备入行开发的零基础员学习python。python也是爬虫、大数据、人工智能等知识的基础。感兴趣的小伙伴可以评论区留言&#xff0c;领取视频教程资料和小编一起学习&#xff0c;共同进步&#xff01;https://www.bilibili.com/video/BV13D4y1G7pt/?…...

3款强大到离谱的电脑软件,个个提效神器,从此远离加班

推荐3款让你偷懒&#xff0c;让你上头的提效电脑软件&#xff0c;个个功能强大&#xff0c;让你远离加班&#xff01; 很多几个小时才能做好的事情&#xff0c;用上它们&#xff0c;只需要5分钟就行&#xff01;&#xff01; 1、JNPF —— 个人最喜欢的低代码软件 它为开发者…...

vue3 使用typescript小结

最近学习vue3 typescript&#xff0c;网上看了很多文章&#xff0c;汇总一下&#xff0c;分享给大家&#xff0c;希望会对大家有帮助。 一. 为props标注类型 defineProps()宏函数支持从它的参数中推导类型&#xff1a; <script setup langts>import { defineProps } fro…...

PYTHON爬虫基础

一、安装package 在使用爬虫前&#xff0c;需要先安装三个包&#xff0c;requests、BeautifulSoup、selenium。 输入如下代码&#xff0c;若无报错&#xff0c;则说明安装成功。 import requests from bs4 import BeautifulSoup import selenium二、Requests应用 了解了原理…...

JavaScript刷LeetCode模板技巧篇(一)

虽然很多人都觉得前端算法弱&#xff0c;但其实 JavaScript 也可以刷题啊&#xff01;最近两个月断断续续刷完了 leetcode 前 200 的 middle hard &#xff0c;总结了一些刷题常用的模板代码。 常用函数 包括打印函数和一些数学函数。 const _max Math.max.bind(Math); co…...

ros-sensor_msgs/PointCloud2消息内容解释

1.字段解释 header-----头文件&#xff0c;包含消息的序列号&#xff0c;时间戳(系统时间)和坐标系id&#xff0c;其中secs为秒&#xff0c;nsecs为去除秒数后剩余的纳秒数 height-----点云的高度&#xff0c;如果是无序点云&#xff0c;则为1&#xff0c;例子中的点云为有序点…...

LeetCode 每日一题2347. 最好的扑克手牌

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

MMPBSA计算--基于李继存老师gmx_mmpbsa脚本

MMPBSA计算–基于李继存老师gmx_mmpbsa脚本 前期准备 软件安装 安装gromacs, 可以查阅 我的blogGromacs-2022 GPU-CUDA加速版 unbantu 安装 apbs, sudo apt install apbs 安装 gawk, sudo apt install gawk MD模拟好的文件 我们以研究蛋白小分子动态相互作用-III(蛋白配体…...

Kafka优化篇-压测和性能调优

简介 Kafka的配置详尽、复杂&#xff0c;想要进行全面的性能调优需要掌握大量信息&#xff0c;这里只记录一下我在日常工作使用中走过的坑和经验来对kafka集群进行优化常用的几点。 Kafka性能调优和参数调优 性能调优 JVM的优化 java相关系统自然离不开JVM的优化。首先想到…...

MinIo-SDK

3.2.5 SDK 3.2.5.1上传文件 MinIO提供多个语言版本SDK的支持&#xff0c;下边找到java版本的文档&#xff1a; 地址&#xff1a;https://docs.min.io/docs/java-client-quickstart-guide.html 最低需求Java 1.8或更高版本: maven依赖如下&#xff1a; XML<dependency&g…...

系统分析师真题2018试卷相关概念一

面向对象的基本概念: 对象的三要素为:属性(数据)、方法(操作)、对象ID(标识)UML2.0包括14种图: 类图(class diagram):类图描述一组类、接口、协作和他们之间的关系。在OO系统的建模中,最常见的图就是类图。类图给出了系统的静态设计图,活动类的类图给出了系统的静…...

身为大学生,你不会还不知道有这些学生福利吧!!!!

本文介绍的是利用学生身份可以享受到的相关学生优惠权益&#xff0c;但也希望各位享受权利的同时不要忘记自己的义务&#xff0c;不要售卖、转手自己的学生优惠资格&#xff0c;使得其他同学无法受益。 前言 高考已经过去&#xff0c;我们也将迎来不同于以往的大学生活&#x…...

试题 算法训练 藏匿的刺客

问题描述 强大的kAc建立了强大的帝国&#xff0c;但人民深受其学霸及23文化的压迫&#xff0c;于是勇敢的鹏决心反抗。   kAc帝国防守森严&#xff0c;鹏带领着小伙伴们躲在城外的草堆叶子中&#xff0c;称为叶子鹏。   kAc帝国的派出的n个看守员都发现了这一问题&#xff…...

JavaWab开发的总括以及HTML知识

一、Web开发的总括在这里我来给大家介绍一下Wab开发需要配合哪些前后端的对应语言:首先是Java(Java通常的工作):Wab开发android开发大数据开发另外,Wab开发想要学好就需要配合之前博客中的内容,如:多线程/IO/网络/数据结构/数据库......这里建议学懂前面的内容再往下走.JavaWab…...

Oracle数据库文件(*.dbf)迁移【图文教程】

目录 背景 解决 第1步:sqlplus登录 第2步:查看Oracle数据文件所在目录 第3步:修改表空间为离线状态 第4步: 移动数据库文件到新目录 第5步:修改表空间数据文件位置 第6步:修改表空间为online状态 第7步:临时表空间处理 第8步:验证修改是否成功 参考...

Java中如何创建和使用对象?

要想使用一个类则必须要有对象。在Java程序中可以使用new关键字创建对象&#xff0c;具体格式如下&#xff1a;类名对象名称null; 对象名称new 类名();上述格式中&#xff0c;创建对象分为声明对象和实例化对象两步&#xff0c;也可以直接通过下面的方式创建对象&#xff0c;具…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...