Define two light source structures: parallel light and point light source
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "shader.h"
#include "stb_image.h"
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include "Camera.h"
GLfloat 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
};
Camera* myCamera = new Camera(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
myCamera->mouseCb(xpos, ypos);
};
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
myCamera->scrollCb(xoffset, yoffset);
}
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
void processInput(GLFWwindow* window) {
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
myCamera->pressKeyW(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
myCamera->pressKeyS(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
myCamera->pressKeyA(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
myCamera->pressKeyD(deltaTime);
}
}
glm::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)
};
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)
};
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "test", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
glfwTerminate();
return -1;
}
glViewport(0, 0, 800, 600);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
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);
GLuint lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
// 只需要绑定VBO不用再次设置VBO的数据,因为容器(物体)的VBO数据中已经包含了正确的立方体顶点数据
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
int width, height;
unsigned char* image = stbi_load("container2.png", &width, &height, 0, 0);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
unsigned char* image1 = stbi_load("container2_specular.png", &width, &height, 0, 0);
GLuint tex1;
glGenTextures(1, &tex1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
glGenerateMipmap(GL_TEXTURE_2D);
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
glEnable(GL_DEPTH_TEST);
Shader* testShader = new Shader("test.vert", "test.frag");
glm::vec3 lightColor(0.33f, 0.42f, 0.18f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (0.33f, 0.21f, 0.06f);
//保持灯不受其他光照影响一直明亮,创建另外一套着色器。
Shader* lightShader = new Shader("test.vert", "light.frag");
while (!glfwWindowShouldClose(window))
{
processInput(window);
glfwPollEvents();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
testShader->Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "material.diffuse"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex1);
glUniform1i(glGetUniformLocation(testShader->getProgram(), "material.specular"), 1);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "material.shininess"), 32.0f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "objectColor"), 1.0f, 0.5f, 0.31f);// 设置物体颜色珊瑚红
glUniform3f(glGetUniformLocation(testShader->getProgram(), "lightColor"), 1.0f, 1.0f, 1.0f); // 把光源设置为白色
view = myCamera->getViewMat4();
glUniformMatrix4fv(glGetUniformLocation(testShader->getProgram(), "view"), 1, GL_FALSE, glm::value_ptr(view));
projection = glm::perspective(glm::radians(myCamera->getFov()), 800.0f / 600.0f, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(testShader->getProgram(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glm::vec3 viewPos = myCamera->getCameraPos();
glUniform3f(glGetUniformLocation(testShader->getProgram(), "viewPos"), viewPos.x, viewPos.y, viewPos.z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "dirLight.direction"), -0.2f, -1.0f, -0.3f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "dirLight.specular"), 0.5f, 0.5f, 0.5f);
glm::vec3 cameraFront = myCamera->getCameraPos();
glUniform3f(glGetUniformLocation(testShader->getProgram(), "light.direction"), cameraFront.x, cameraFront.y, cameraFront.z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].constant"), 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].linear"), 0.09);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[0].quadratic"), 0.032);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].constant"), 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].linear"), 0.09);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[1].quadratic"), 0.032);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].constant"), 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].linear"), 0.09);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[2].quadratic"), 0.032);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].constant"), 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].linear"), 0.09);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "pointLights[3].quadratic"), 0.032);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "spotLight.position"), cameraFront.x, cameraFront.y, cameraFront.z);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "spotLight.ambient"), 0.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "spotLight.diffuse"), 1.0f, 1.0f, 1.0f);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "spotLight.specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "spotLight.constant"), 1.0f);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "spotLight.linear"), 0.09);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "spotLight.quadratic"), 0.032);
glUniform3f(glGetUniformLocation(testShader->getProgram(), "spotLight.direction"), cameraFront.x, cameraFront.y, cameraFront.z);
glUniform1f(glGetUniformLocation(testShader->getProgram(), "spotLight.cutOff"), glm::cos(glm::radians(12.5f)));
glUniform1f(glGetUniformLocation(testShader->getProgram(), "spotLight.outerCutOff"), glm::cos(glm::radians(15.0f)));
glBindVertexArray(VAO);
for (GLuint i = 0; i < 10; i++)
{
model = glm::mat4();
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(glGetUniformLocation(testShader->getProgram(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(lightVAO);
//平移灯源位置到lightPos
lightShader->Use();
glUniformMatrix4fv(glGetUniformLocation(lightShader->getProgram(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(lightShader->getProgram(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
for (GLuint i = 0; i < 4; i++)
{
model = glm::mat4();
model = glm::translate(model, pointLightPositions[i]);
model = glm::scale(model, glm::vec3(0.2f));
glUniformMatrix4fv(glGetUniformLocation(lightShader->getProgram(), "model"), 1, GL_FALSE, glm::value_ptr(model));
// 绘制灯立方体对象
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
vertex shader
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal; //面的法向量
layout (location = 2) in vec2 texCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 Normal;
out vec3 FragPos; //片段位置
out vec2 TexCoords;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0);
FragPos = vec3(model * vec4(position, 1.0f));
Normal = mat3(transpose(inverse(model))) * normal;
TexCoords = texCoords;
}
fragment shader
#version 330 core
out vec4 color;
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;
uniform vec3 objectColor;
uniform vec3 lightColor;
struct Material
{
sampler2D diffuse;
sampler2D specular;
float shininess;
};
uniform Material material;
uniform vec3 viewPos;
//平行光
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform DirLight dirLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); //因为定义写在main函数后,所以要在main函数前先声明,才能再main函数中调用
//点光源
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 4
uniform PointLight pointLights[NR_POINT_LIGHTS];
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
struct SpotLight
{
vec3 position;
vec3 direction;
float cutOff; //切光角
float outerCutOff; //外切角
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform SpotLight spotLight;
vec3 CalcSpotLight(SpotLight spotLight,vec3 normal,vec3 fragPos,vec3 viewDir);
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);*/
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); //计算顶点光照
}
// 第三部,计算 Spot light
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);
}
vec3 CalcSpotLight(SpotLight spotLight,vec3 normal,vec3 fragPos,vec3 viewDir)
{
vec3 lightDir = normalize(spotLight.position - FragPos);
float theta = dot(lightDir, normalize(spotLight.direction));
float epsilon = spotLight.cutOff - spotLight.outerCutOff;
float intensity = clamp((theta - spotLight.outerCutOff) / epsilon,0.0, 1.0);
vec3 ambient = spotLight.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 norm = normalize(Normal);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = spotLight.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = spotLight.specular * spec * vec3(texture(material.specular, TexCoords));
float distance = length(spotLight.position - FragPos);//光源的距离
float attenuation = 1.0f / (spotLight.constant + spotLight.linear*distance +spotLight.quadratic*(distance*distance));
diffuse *= attenuation;
specular *= attenuation;
diffuse *= intensity;
specular *= intensity;
return (ambient + diffuse + specular);
}
Exercise:
It is to adjust the various parameters of light to achieve various effects.