LearOpenGL 光照片段着色器

#version 460 
out vec4 FragColor;

// 定义一个名为Material的结构体,用于存储3D物体的材质信息。
struct Material {
    // 漫反射纹理贴图,用于存储物体表面在漫反射下的颜色信息。
    // sampler2D表示这是一个二维纹理贴图,一般在图形渲染中使用。
	sampler2D diffuse; 
    // 镜面纹理贴图,用于存储物体表面在镜面反射下的高光区域的颜色信息。
    // sampler2D表示这是一个二维纹理贴图,一般在图形渲染中使用。
	sampler2D specular; 
    // 反光度,用于控制物体表面的镜面反射效果的程度。
    // 通常这个值越大,物体表面的镜面反射效果越强烈。
	float shininess;
};

// 方向光结构体
struct DirLight {
    // 光线方向,表示从光源出发射向物体的方向
	vec3 direction; // 表示方向的光线向量

    // 环境光,表示物体表面被照亮的程度,不受光照角度影响
	vec3 ambient; // 表示环境光的颜色

    // 漫反射光,表示物体表面在漫反射下的颜色分布
	vec3 diffuse; // 表示漫反射光的颜色

    // 镜面反射光,表示物体表面在镜面反射下的颜色分布
	vec3 specular; // 表示镜面反射光的颜色
};

// 定义一个名为PointLight的结构体
struct PointLight {
    // 表示点光源的位置。使用vec3表示三维坐标,x、y和z分别代表横轴、纵轴和竖轴。
	vec3 position;

    // 表示光照衰减的常数项。在光照计算中,这个值用于决定光源距离物体越远,其亮度衰减的程度。
	float constant;
    // 表示光照衰减的线性项。这个值通常与光源距离物体的距离线性相关,用于增强光照衰减的效果。
	float linear;
    // 表示光照衰减的二次项。这个值通常与光源距离物体的距离的平方相关,用于增强光照衰减的效果。
	float quadratic;

    // 表示环境光的颜色。环境光是均匀分布在场景中的光线,不依赖于物体的位置或朝向。
	vec3 ambient;
    // 表示漫反射光的颜色。漫反射是光线在物体表面反射时,朝各个方向均匀散射的现象。
	vec3 diffuse;
    // 表示镜面反射光的颜色。镜面反射是光线在物体表面反射时,朝特定方向集中反射的现象。
	vec3 specular;
};

// 聚光灯结构体用于存储一个聚光灯的相关属性
struct SpotLight {
	// 聚光灯的位置,以三维向量 (x, y, z) 表示。这个向量通常用于确定灯在三维空间中的位置。
	vec3 position;
	// 聚光灯的方向,以三维向量 (x, y, z) 表示。这个向量通常用于确定灯照射的方向。
	vec3 direction;
	// 聚光灯的内锥角度(以弧度为单位)。这个值用于描述灯的照射范围,即光线在内部的角度。
	float cutOff;
	// 聚光灯的外锥角度(以弧度为单位)。这个值用于描述灯的外部照射范围,即光线在外部的角度。
	float outerCutOff;

	// 表示光照衰减的常数项。在光照计算中,这个值用于决定光源距离物体越远,其亮度衰减的程度。
	float constant;
    // 表示光照衰减的线性项。这个值通常与光源距离物体的距离线性相关,用于增强光照衰减的效果。
	float linear;
    // 表示光照衰减的二次项。这个值通常与光源距离物体的距离的平方相关,用于增强光照衰减的效果。
	float quadratic;

    // 表示环境光的颜色。环境光是均匀分布在场景中的光线,不依赖于物体的位置或朝向。
	vec3 ambient;
    // 表示漫反射光的颜色。漫反射是光线在物体表面反射时,朝各个方向均匀散射的现象。
	vec3 diffuse;
    // 表示镜面反射光的颜色。镜面反射是光线在物体表面反射时,朝特定方向集中反射的现象。
	vec3 specular;
};

// 定义NR_POINT_LIGHTS常量,表示点光源的数量为4
#define NR_POINT_LIGHTS 4

// 定义一个包含NR_POINT_LIGHTS个元素的PointLight数组,存储点光源的信息
uniform PointLight pointLights[NR_POINT_LIGHTS];

// 定义一个DirLight变量,存储方向光源的信息
uniform DirLight dirLight;

// 定义一个Material变量,存储材质的信息
uniform Material material;

// 定义一个SpotLight变量,存储聚光灯的信息
uniform SpotLight spotLight;

// 定义一个vec3类型的viewPos变量,表示摄像机的位置
uniform vec3 viewPos; // 摄像机位置

// 定义一个in变量FragPos,表示顶点坐标(世界空间)
in vec3 FragPos; // 顶点坐标(世界空间)

// 定义一个in变量Normal,表示顶点的法线向量
in vec3 Normal; // 顶点法线

// 定义一个in变量TexCoords,表示纹理坐标
in vec2 TexCoords; // 纹理坐标


// CalcDirLight函数用于计算方向光对给定表面的影响
// 输入参数:
//   light - 方向光信息,包括颜色、方向等
//   normal - 表面法向量,表示表面朝向和角度
//   viewDir - 视线方向,表示观察者的朝向
// 返回值:
//   返回一个vec3类型的值,表示方向光对表面特定点的照射颜色
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);

// calcPointLight函数用于计算点光源对给定表面的影响
// 输入参数:
//   light - 点光源信息,包括位置、衰减系数以及颜色等信息
//   normal - 表面法向量,表示表面朝向和角度
//   fragPos - 片段位置,表示表面上的某一点
//   viewDir - 视线方向,表示观察者的朝向
// 返回值:
//   返回一个vec3类型的值,表示点光源对表面特定点的照射颜色
vec3 calcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);

// 计算聚光灯对物体表面的影响
// 参数:
//   light:聚光灯的参数
//   normal:物体表面的法线向量
//   fragPos:物体表面的一个点
//   viewDir:视线方向向量
// 返回值:
//   聚光灯对物体表面的光照结果,以颜色向量的形式表示
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);

void main() {

    // 计算法向量N,这里假设Normal是给定的法向量
    // 通常Normal是从顶点数据或模型数据中获取的,表示表面的法线方向
    vec3 N = normalize(Normal);

    // 计算视线向量V,viewPos是视点的位置,FragPos是当前片段的位置
    // normalize函数确保V是一个单位向量,即长度为1的向量
    vec3 V = normalize(viewPos - FragPos);

    // 计算方向光对物体表面的影响,并将结果存储在result变量中
    // CalcDirLight是一个函数,它接受方向光、法向量和视线向量作为参数
    // 这个函数可能包含一些计算,如计算光线与表面的角度等,以确定方向光的照射强度
    vec3 result = CalcDirLight(dirLight, N, V);

    // 遍历所有的点光源
    // NR_POINT_LIGHTS是一个常量,表示场景中点光源的数量
    for(int i = 0; i < NR_POINT_LIGHTS; i++) {
        // 对于每个点光源,调用calcPointLight函数来计算其对物体表面的影响
        // 这个函数可能涉及到距离计算、光照衰减等计算
        result += calcPointLight(pointLights[i], N, FragPos, V);
    }

    // 计算聚光灯对物体表面的影响,并将结果累加到result中
    // CalcSpotLight是一个函数,它接受聚光灯、法向量、片段位置和视线向量作为参数
    // 这个函数可能包含对聚光灯的照射范围、角度等的计算
    result += CalcSpotLight(spotLight, N, FragPos, V);

    // 将最终的光照结果赋值给FragColor,这是一个vec4类型的变量,其中result是颜色,1.0是透明度
    // vec4(result, 1.0)表示将result作为颜色的RGBA值,并将透明度设置为1.0(完全不透明)
    FragColor = 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);
    // dot(normal, lightDir) 计算法向量和光线方向的点积,max(dot(normal, lightDir), 0.0) 确保当光线方向与法线方向相反时,漫反射光照强度为0

    // 计算反射方向
    vec3 reflectDir = reflect(-lightDir, normal);
    // reflect函数计算光线在物体表面的反射方向,-lightDir是入射光线的反方向,normal是物体的法向量

    // 计算高光反射光照强度
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // max(dot(viewDir, reflectDir), 0.0) 确保当反射光线与视线方向相反时,高光反射光照强度为0
    // pow(…, material.shininess) 根据物体的粗糙度(或高光反射度)调整高光反射强度

    // 从纹理中获取物体的漫反射颜色
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
    // diffuse * diff 调整漫反射光的强度,因为diff是漫反射光照强度

    // 从纹理中获取物体的漫反射颜色
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));

    // 从纹理中获取物体的高光反射颜色
    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    // specular * spec 调整高光反射光的强度,因为spec是高光反射光照强度

    // 返回总的光照结果,即环境光、漫反射光和高光反射光的和
    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);
    // dot(normal, lightDir) 计算法向量和光线方向的点积,max(dot(normal, lightDir), 0.0) 确保当光线方向与法线方向相反时,漫反射光照强度为0

    // 计算反射方向
    vec3 reflectDir = reflect(-lightDir, normal);
    // reflect函数计算光线在物体表面的反射方向,-lightDir是入射光线的反方向,normal是物体的法向量

    // 计算高光反射光照强度
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // max(dot(viewDir, reflectDir), 0.0) 确保当反射光线与视线方向相反时,高光反射光照强度为0
    // pow(…, material.shininess) 根据物体的粗糙度(或高光反射度)调整高光反射强度

    // 计算从点光源到物体表面的距离
    float distance = length(light.position - fragPos);
    // length函数计算两点之间的距离

    // 计算光照衰减
    float attenuation = 1.0 / (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));
    // diffuse * diff 调整漫反射光的强度,因为diff是漫反射光照强度

    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    // specular * spec 调整高光反射光的强度,因为spec是高光反射光照强度

    // 根据光照衰减调整环境光、漫反射光和镜面反射光的强度
    ambient *= attenuation;
    diffuse *= attenuation;
    specular *= attenuation;

    // 返回总的光照结果,即环境光、漫反射光和镜面反射光的和
    return (ambient + diffuse + specular);
}

// 计算聚光灯对物体表面的影响
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) {

    // 计算从物体表面点到聚光灯的光线方向
    vec3 lightDir = normalize(light.position - fragPos);

    // 计算漫反射光照强度
    float diff = max(dot(normal, lightDir), 0.0);
    // dot(normal, lightDir) 计算法向量和光线方向的点积,max(dot(normal, lightDir), 0.0) 确保当光线方向与法线方向相反时,漫反射光照强度为0

    // 计算反射方向
    vec3 reflectDir = reflect(-lightDir, normal);
    // reflect函数计算光线在物体表面的反射方向,-lightDir是入射光线的反方向,normal是物体的法向量

    // 计算高光反射光照强度
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // max(dot(viewDir, reflectDir), 0.0) 确保当反射光线与视线方向相反时,高光反射光照强度为0
    // pow(…, material.shininess) 根据物体的粗糙度(或高光反射度)调整高光反射强度

    // 计算从聚光灯到物体表面的距离
    float distance = length(light.position - fragPos);
    // length函数计算两点之间的距离

    // 计算光照衰减
    float attenuation = 1.0 / (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));
    // diffuse * diff 调整漫反射光的强度,因为diff是漫反射光照强度

    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    // specular * spec 调整高光反射光的强度,因为spec是高光反射光照强度

    // 计算光线与聚光灯锥体的角度差
    float theta = dot(lightDir,normalize(-light.direction));
    // normalize(-light.direction) 将聚光灯的方向归一化,以便与光线方向进行点积运算

    // 计算聚光灯的内外锥体角度差
    float epsilon = light.cutOff - light.outerCutOff;
    // cutOff和outerCutOff分别是聚光灯的内锥体和外锥体角度

    // 计算光照强度权重
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
    // (theta - light.outerCutOff) / epsilon 计算光照强度权重,clamp函数确保其值在0到1之间

    // 根据光照衰减和光照强度权重对环境光、漫反射光和镜面反射光进行缩放
    ambient *= attenuation * intensity;
    diffuse *= attenuation * intensity;
    specular *= attenuation * intensity;

    // 返回总的光照结果,即环境光、漫反射光和镜面反射光的和
    return (ambient + diffuse + specular);
}

main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <iostream>
#include <assert.h>
#include <cmath>
#include <stack>
#include <vector>
#include <Class/Shader/Shader.h>
#include <Class/Camera/Camera.h>

// 创建多少个 VAO VBO 
#define ARRAYMAXCOUNT 1
// 创建 vao 变量
GLuint vao[ARRAYMAXCOUNT+1];
// 创建 vbo
GLuint vbo[ARRAYMAXCOUNT];

// 创建着色器类
Shader shader1;
Shader shader2;

// 摄像机
Camera myCamera(glm::vec3(0.0f, 0.0f, 3.0f),glm::vec3(0.0f, 0.0f, -1.0f),glm::vec3(0.0f, 1.0f, 0.0f));

GLuint
texture1,// 纹理
texture2,// 纹理
vLoad,// 视图矩阵
mLoad,// 模型矩阵
pLoad;// 透视矩阵

glm::mat4
mMat,	// 模型矩阵
pMat,  // 透视矩阵
vMat;  // 视图矩阵

// 光源位置
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

// 10 个箱子的位置
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)
};

// 初始自定义代码
void init(GLFWwindow* window);
// 渲染自定义代码
void display(GLFWwindow* window, double currentTime);
// 销毁
void destroy(GLFWwindow* window);
// 窗口改变事件
void window_reshape_callback(GLFWwindow* window, int width, int height);
// 注册了鼠标移动事件
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
// 注册了鼠标移动事件
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
// 监听按键,鼠标事件
void ProcessInput(GLFWwindow* window);

int main() {
	// 初始化 glfw
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	// 设置 opengl 版本 (4.6 核心)
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	// 创建 window 窗口
	GLFWwindow* window = glfwCreateWindow(600, 600, "LearOpenGL 1.10", NULL, NULL);
	// 链接 opengl 上下文
	glfwMakeContextCurrent(window);

	// 初始化 glad 获取 opengl api 函数 地址
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { exit(EXIT_FAILURE); }
	// 开启垂直
	glfwSwapInterval(1);

	// 注册窗口改变事件
	glfwSetWindowSizeCallback(window, window_reshape_callback);
	// 隐藏光标
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	// 注册了鼠标移动事件
	glfwSetCursorPosCallback(window, mouse_callback);
	// 注册了鼠标滚动事件
	glfwSetScrollCallback(window, scroll_callback);

	// 初始化着色器类
	shader1.init("vertShader1.glsl","fragShader1.glsl");
	shader2.init("vertShader2.glsl","fragShader2.glsl");

	// 初始自定义代码
	init(window);

	myCamera.fov = 45.0f;

	// 循环渲染
	while (!glfwWindowShouldClose(window))
	{
		// 监听键盘
		ProcessInput(window);

		// 渲染自定义代码
		display(window, glfwGetTime());

		// 交换缓存和轮询IO事件
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	// 释放内存
	destroy(window);

	// 成功退出程序
	exit(EXIT_SUCCESS);
}

void init(GLFWwindow* window) {

	// 创建 vao 
	glGenVertexArrays(ARRAYMAXCOUNT + 1, vao);
	// 创建 vbo
	glGenBuffers(ARRAYMAXCOUNT, vbo);

	float vertices[] = {
		// 顶点				 // 法向量			  // 纹理
	   -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
	};

	// 绑定 vao
	glBindVertexArray(vao[0]);

	// 把顶点数据绑定到 vbo
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 设置属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 6));
	glEnableVertexAttribArray(2);

	// 绑定 vao
	glBindVertexArray(vao[1]);
	// 把顶点数据绑定到 vbo
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	// 设置属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// 创建纹理
	glGenTextures(1, &texture1);
	Utils::image image;
	image.imagePath = "dm\\container2.png";
	image.Isreversed = true;
	image.type = GL_RGBA;
	// 绑定纹理
	glBindTexture(GL_TEXTURE_2D, texture1);
	Utils::getImage(image);

	glGenTextures(1, &texture2);
	image.imagePath = "dm\\container2_specular.png";
	glBindTexture(GL_TEXTURE_2D, texture2);
	Utils::getImage(image);

	// 开启着色器程序
	shader1.useProgram();
	mLoad = shader1.getULocation("m_matrix");
	vLoad = shader1.getULocation("v_matrix");
	pLoad = shader1.getULocation("p_matrix");

	// 3D物体的材质信息
	shader1.setPUInt("material.diffuse", 0);			// 漫反射光照
	shader1.setPUInt("material.specular", 1);			// 镜面光照
	shader1.setPUFloat("material.shininess", 32.0f);	// 反光度

	// 方向光结构体
	shader1.setPUF3fv_t("dirLight.direction", glm::value_ptr(glm::vec3(-0.2f, -1.0f, -0.3f)));// 光线位置
	shader1.setPUF3fv_t("dirLight.ambient", glm::value_ptr(glm::vec3(0.05f, 0.05f, 0.05f)));// 环境光照
	shader1.setPUF3fv_t("dirLight.diffuse", glm::value_ptr(glm::vec3(0.4f, 0.4f, 0.4f)));// 漫反射光照
	shader1.setPUF3fv_t("dirLight.specular", glm::value_ptr(glm::vec3(0.5f, 0.5f, 0.5f)));// 镜面光照

	// 点光源
	for (int i = 0; i < 4; i++)
	{
		std::string position = "pointLights[0].position";
		std::string ambient = "pointLights[0].ambient";
		std::string diffuse = "pointLights[0].diffuse";
		std::string specular = "pointLights[0].specular";
		std::string constant = "pointLights[0].constant";
		std::string linear = "pointLights[0].linear";
		std::string quadratic = "pointLights[0].quadratic";

		position.replace(12, 1, std::to_string(i));
		ambient.replace(12, 1, std::to_string(i));
		diffuse.replace(12, 1, std::to_string(i));
		specular.replace(12, 1, std::to_string(i));
		constant.replace(12, 1, std::to_string(i));
		linear.replace(12, 1, std::to_string(i));
		quadratic.replace(12, 1, std::to_string(i));

		glm::vec3 lightColor;
		lightColor.x = std::sin(2.0f * (i + 1));
		lightColor.y = std::sin(0.7f * (i + 1));
		lightColor.z = std::sin(1.3f * (i + 1));

		glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // 降低影响
		glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影响

		shader1.setPUF3fv_t(position.c_str(), glm::value_ptr(pointLightPositions[i]));// 光线位置
		shader1.setPUF3fv_t(ambient.c_str(), glm::value_ptr(ambientColor));// 环境光照
		shader1.setPUF3fv_t(diffuse.c_str(), glm::value_ptr(diffuseColor));// 漫反射光照
		shader1.setPUF3fv_t(specular.c_str(), glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));// 镜面光照
		// 实现光的衰弱
		shader1.setPUFloat(constant.c_str(), 1.0f);// 常数项 
		shader1.setPUFloat(linear.c_str(), 0.09f);// 一次项
		shader1.setPUFloat(quadratic.c_str(), 0.032f);// 二次项 
	}

	shader1.setPUF3fv_t("spotLight.ambient", glm::value_ptr(glm::vec3(0.0f, 0.0f, 0.0f)));// 环境光照
	shader1.setPUF3fv_t("spotLight.diffuse", glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));// 漫反射光照
	shader1.setPUF3fv_t("spotLight.specular", glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f)));// 镜面光照
	// 实现光的衰弱
	shader1.setPUFloat("spotLight.constant", 1.0f);// 常数项 
	shader1.setPUFloat("spotLight.linear", 0.09f);// 一次项
	shader1.setPUFloat("spotLight.quadratic", 0.032f);// 二次项 
	shader1.setPUFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
	shader1.setPUFloat("spotLight.outerCutOff", glm::cos(glm::radians(15.0f)));

	// 获取窗口的宽高
	int width, height;
	glfwGetFramebufferSize(window, &width, &height);// 获取屏幕宽,高
	// 计算宽高比
	float aspect = (float)width / (float)height;//获取屏幕比例
	// 创建透视矩阵 / 设置投影矩阵
	pMat = glm::perspective(glm::radians(myCamera.fov), aspect, 0.1f, 1000.0f);
}

void display(GLFWwindow* window, double currentTime) {
	// 填充颜色缓冲区
	glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
	// 清除深度缓冲区
	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

	// 创建透视矩阵 / 设置投影矩阵
	pMat = glm::perspective(glm::radians(myCamera.fov), (float)600 / (float)600, 0.1f, 1000.0f);
	// 将视图矩阵压入栈
	vMat = myCamera.getLookAt();

	// 开启着色器程序
	shader1.useProgram();

	

	shader1.setPUF3fv_t("spotLight.position", glm::value_ptr(myCamera.cameraPos));// 光线位置
	shader1.setPUF3fv_t("spotLight.direction", glm::value_ptr(myCamera.cameraFront));// 光线位置
	// 摄像机位置
	shader1.setPUF3fv_t("viewPos", glm::value_ptr(myCamera.cameraPos));

	// 视图矩阵
	shader1.setPUFMat4(vLoad, glm::value_ptr(vMat));
	// 透视矩阵
	shader1.setPUFMat4(pLoad, glm::value_ptr(pMat));

	// 将纹理绑定到相应的纹理单元上
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texture1);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, texture2);

	// 开启深度测试
	glEnable(GL_DEPTH_TEST);
	// 设置深度测试的比较方式
	glDepthFunc(GL_LEQUAL);
	// 绑定 vao
	glBindVertexArray(vao[0]);

	for (int i = 0; i < 10; i++)
	{
		// 模型矩阵
		mMat = glm::translate(glm::mat4(1.0f), cubePositions[i]);

		float angle = 20.0f * i;
		mMat = glm::rotate(mMat, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));

		// 模型矩阵
		shader1.setPUFMat4(mLoad, glm::value_ptr(mMat));

		// 绘制模型
		glDrawArrays(GL_TRIANGLES, 0, 36);
	}

	// 开启着色器程序
	shader2.useProgram();
	// 开启深度测试
	glEnable(GL_DEPTH_TEST);
	// 设置深度测试的比较方式
	glDepthFunc(GL_LEQUAL);
	// 绑定 vao
	glBindVertexArray(vao[1]);
	for (int i = 0; i < 4; i++)
	{
		// 模型矩阵
		mMat = glm::translate(glm::mat4(1.0f), pointLightPositions[i]);
		mMat = glm::rotate(mMat, (float)currentTime * glm::radians(45.0f), glm::vec3(1.0f, 0.5f, 0.0f));
		mMat = glm::scale(mMat, glm::vec3(0.2f, 0.2f, 0.2f));

		glm::vec3 lightColor;
		lightColor.x = std::sin(2.0f * (i + 1));
		lightColor.y = std::sin(0.7f * (i + 1));
		lightColor.z = std::sin(1.3f * (i + 1));

		glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // 降低影响
		glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影响

		lightColor = diffuseColor;

		shader2.setPUFMat4("mv_matrix", glm::value_ptr(vMat * mMat));
		shader2.setPUFMat4("p_matrix", glm::value_ptr(pMat));
		shader2.setPUFloat("lightColor", lightColor.x, lightColor.y, lightColor.z);
		// 绘制模型
		glDrawArrays(GL_TRIANGLES, 0, 36);
	}
}

void destroy(GLFWwindow* window) {
	// 销毁 vao vbo
	glDeleteVertexArrays(ARRAYMAXCOUNT, vao);
	glDeleteBuffers(ARRAYMAXCOUNT, vbo);
	// 销毁着色器
	shader1.deleteProgram();
	// 销毁窗口
	glfwDestroyWindow(window);
	glfwTerminate();
}

void window_reshape_callback(GLFWwindow* window, int width, int height)
{
	// 设置和帧缓冲区相关的屏幕区域
	glViewport(0, 0, width, height);
}

// 监听按键,鼠标事件
void ProcessInput(GLFWwindow* window)
{
	// 检查用户是否按下了返回键(Esc)
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
	{
		// 下一次while循环的条件检测将会失败,程序将会关闭
		glfwSetWindowShouldClose(window, true);
	}
	static float deltaTime = 0.0f;
	static float lastFrame = 0.0f;

	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame; //  当前帧与上一帧的时间差
	lastFrame = currentFrame;             //  上一帧的时间

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		myCamera.ProcessKeyboard(FORWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		myCamera.ProcessKeyboard(BACKWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		myCamera.ProcessKeyboard(LEFT, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		myCamera.ProcessKeyboard(RIGHT, deltaTime);
}

// 回调函数,鼠标进入程序窗口,获取焦点
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	static bool firstMouse = true;
	static float lastX = 0.0f;
	static float lastY = 0.0f;
	static float xoffset = 0.0f;
	static float yoffset = 0.0f;

	if (firstMouse)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;
	}

	// 获取 x 坐标
	xoffset = xpos - lastX;
	// 注意这里是相反的,因为y坐标是从底部往顶部依次增大的
	yoffset = lastY - ypos;

	// 更新鼠标坐标
	lastX = xpos;
	lastY = ypos;

	myCamera.mouse_callback(xoffset, yoffset);
}

// 监听鼠标滚动
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	myCamera.scroll_callback(xoffset, yoffset);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值