当前位置: 首页 > 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;具…...

Spring Cloud Alibaba--ActiveMQ微服务详解之消息队列(四)

上篇讲述高并发情况下的数据库处理方式&#xff1a;分布式事务管理机制。即使我们做到这一步并发情况只能稍微得到缓解&#xff0c;当然千万级别的问题不大&#xff0c;但在面对双十一淘宝这类的达上亿的并发的时候仅仅靠分布式事务管理还是远远不够&#xff0c;即使数据库可以…...

32岁,薪水被应届生倒挂,裸辞了

今年 32 岁&#xff0c;我从公司离职了&#xff0c;是裸辞。 前段时间&#xff0c;我有一件事情一直憋在心里很难受&#xff0c;想了很久也没找到合适的人倾诉&#xff0c;就借着今天写出来。 我一个十几年开发经验&#xff0c;八年 软件测试 经验的职场老人&#xff0c;我慢…...

蓝桥杯训练day1

前缀和差分1.前缀和(1)3956. 截断数组(2)795. 前缀和(3)796. 子矩阵的和(4)1230. K倍区间(5)99. 激光炸弹2.差分(1)797. 差分(2)差分矩阵(3)3729. 改变数组元素(4)100. 增减序列1.前缀和 (1)3956. 截断数组 方法1&#xff1a;暴力 先用两个数组分别保存前缀和&#xff0c;后缀…...

Unity毛发系统TressFX Exporter

Unity 数字人交流群&#xff1a;296041238 一&#xff1a;在Maya下的TressFX Exporter 插件安装步骤&#xff1a; 1. 下载Maya的TressFX Exporter插件 下载地址&#xff1a;TressFX Exporter 链接&#xff1a;https://github.com/Unity-China/cn.unity.hairfx.core/tree/m…...

《爆肝整理》保姆级系列教程python接口自动化(十九)--Json 数据处理---实战(详解)

简介 上一篇说了关于json数据处理&#xff0c;是为了断言方便&#xff0c;这篇就带各位小伙伴实战一下。首先捋一下思路&#xff0c;然后根据思路一步一步的去实现和实战&#xff0c;不要一开始就盲目的动手和无头苍蝇一样到处乱撞&#xff0c;撞得头破血流后而放弃了。不仅什么…...

Golang:reflect反射的使用例子

1.reflect包作用 reflect包定义了“反射”相关能力&#xff0c;“反射”在计算机学中是指计算机程序在运行时&#xff08;runtime&#xff09;可以访问、检测和修改它本身状态或行为的一种能力。基于反射特性可以通用化地解决一些需要频繁修改代码及硬编码问题&#xff0c;但是…...

markdown常用语法--花括号(超详细)

&#x1f48c; 所属专栏&#xff1a;【Markdown常用语法】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1…...

BN、SyncBN、IN、LN、GN学习记录

1 BatchNormBN的原理BN是计算机视觉最常用的标准化方法&#xff0c;它沿着N、H、W维度对输入特征图求均值和方差&#xff0c;随后再利用均值和方差来归一化特征图。计算过程如下图所示&#xff0c;1&#xff09;沿着通道维度计算其他维度的均值&#xff1b;2&#xff09;沿着通…...

使用 Auto-scheduling 优化算子

本篇回答来源于 TVM 官方英文文档 Lianmin Zheng&#xff0c;Chengfan Jia。更多 TVM 中文文档可访问→https://tvm.hyper.ai/ 本教程将展示 TVM 的 Auto Scheduling 功能&#xff0c;如何在不编写自定义模板的情况下&#xff0c;找到最佳 schedule。 与基于模板的 AutoTVM 依…...

智能运维应用之道,告别企业数字化转型危机

面临的问题及挑战 数据中心发展历程 2000 年中国数据中心始建&#xff0c;至今已经历以下 3 大阶段。早期&#xff1a;离散型数据中心 IT 因以项目建设为导向&#xff0c;故缺乏规划且无专门运维管理体系&#xff0c;此外&#xff0c;开发建设完的项目均是独立运维维护&#…...

简洁汽车配件网站模板/百度知道网页版登录入口

什么是冒泡排序&#xff1f; 是通过挨个的比较&#xff0c;将最大&#xff08;或最小&#xff09;数字层层交换至所有数据的开头&#xff0c;每冒一次&#xff0c;数据头部往后移一位&#xff0c;经过N次冒泡之后&#xff0c;得到最终排序&#xff01;&#xff01;&#xff01…...

竞网做的网站怎么/宁波seo深度优化平台

动态规划思想是将大问题分解成小问题&#xff0c;然后解决所有的小问题&#xff0c;最后把解组合起来就得到大问题的解。这个和分治法思想很类似&#xff0c;但是这里的小问题是有重叠的&#xff0c;分治处理的小问题都是独立的&#xff0c;有重叠就会有重复计算&#xff0c;为…...

做女装的网站/怎么进行网络推广

[Mnsx_x]刷题笔记——顶端迭代器 请你设计一个迭代器&#xff0c;除了支持 hasNext 和 next 操作外&#xff0c;还支持 peek 操作。 实现 PeekingIterator 类&#xff1a; PeekingIterator(int[] nums) 使用指定整数数组 nums 初始化迭代器。 int next() 返回数组中的下一个元素…...

自己做的网站怎么接入网页游戏/百度推广官方网站登录入口

Epoll 对象的创建 在 linux 中&#xff0c;最为高效的 reactor 机制就是 epoll。swReactor 的 object 会存储 epoll 的对象 swReactorEpoll_s。该数据结构中 epfd 是 epoll 的 id&#xff0c;events 用于在 epoll_wait 函数接受就绪的事件。该函数最重要的是 epoll_create&…...

网站搭建代理/网站模板下载

推荐阅读&#xff1a; 这套Github上40Kstar学习笔记&#xff0c;可以帮你搞定95%以上的Java面试 毫不夸张的说&#xff0c;这份SpringBoot学习指南能解决你遇到的98%的问题 最全面试题新鲜出炉&#xff1a;70算法题、近30种大厂面试笔试常考知识点 前言 最近在做的业务场景…...

网站中文域名/软文代发布

题意 N个客户&#xff0c;外卖员需要将外卖送给N个客户。0代表外卖店&#xff0c;1-N代表客户地址。矩阵i,j代表从i到j所需时间。求送完所有外卖最少所需时间。 题解 先使用Flyod算法求出任意两点间最短路&#xff08;数据量很小&#xff0c;Flyod很轻松&#xff09;。然后d…...