计算机图形学(八)——添加一个光源照射立方体

在第(七)节的基础上给正方体添加一个旋转的照射光源

现实世界的光照是极其复杂的,而且会受到诸多因素的影响,这是我们有限的计算能力所无法模拟的。因此OpenGL的光照使用的是简化的模型,对现实的情况进行近似,这样处理起来会更容易一些,而且看起来也差不多一样。这些光照模型都是基于我们对光的物理特性的理解。其中一个模型被称为冯氏光照模型(Phong Lighting Model)。冯氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子:
在这里插入图片描述

环境光照

光通常都不是来自于同一个光源,而是来自于我们周围分散的很多光源,即使它们可能并不是那么显而易见。光的一个属性是,它可以向很多方向发散并反弹,从而能够到达不是非常直接临近的点。所以,光能够在其它的表面上反射,对一个物体产生间接的影响。考虑到这种情况的算法叫做全局照明(Global Illumination)算法,但是这种算法既开销高昂又极其复杂。

由于我们现在对那种又复杂又开销高昂的算法不是很感兴趣,所以我们将会先使用一个简化的全局照明模型,即环境光照。正如你在上一节所学到的,我们使用一个很小的常量(光照)颜色,添加到物体片段的最终颜色中,这样子的话即便场景中没有直接的光源也能看起来存在有一些发散的光。

把环境光照添加到场景里非常简单。我们用光的颜色乘以一个很小的常量环境因子,再乘以物体的颜色,然后将最终结果作为片段的颜色。

漫反射光照

在这里插入图片描述

图左上方有一个光源,它所发出的光线落在物体的一个片段上。我们需要测量这个光线是以什么角度接触到这个片段的。如果光线垂直于物体表面,这束光对物体的影响会最大化(译注:更亮)。为了测量光线和片段的角度,我们使用一个叫做法向量(Normal Vector)的东西,它是垂直于片段表面的一个向量(这里以黄色箭头表示),我们在后面再讲这个东西。这两个向量之间的角度很容易就能够通过点乘计算出来。

你可能记得在变换那一节教程里,我们知道两个单位向量的夹角越小,它们点乘的结果越倾向于1。当两个向量的夹角为90度的时候,点乘会变为0。这同样适用于θ,θ越大,光对片段颜色的影响就应该越小。
所有光照的计算都是在片段着色器里进行,所以我们需要将法向量由顶点着色器传递到片段着色器。我们这么做:

out vec3 Normal;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    Normal = aNormal;
}

在片源着色器中定义相应的输入变量:

in vec3 Normal;

计算漫反射光照

我们现在对每个顶点都有了法向量,但是我们仍然需要光源的位置向量和片段的位置向量。由于光源的位置是一个静态变量,我们可以简单地在片段着色器中把它声明为uniform:

uniform vec3 lightPos;

使用在前面声明的lightPos向量作为光源位置:

lightingShader.setVec3("lightPos", lightPos);

最后,我们还需要片段的位置。我们会在世界空间中进行所有的光照计算,因此我们需要一个在世界空间中的顶点位置。我们可以通过把顶点位置属性乘以模型矩阵(不是观察和投影矩阵)来把它变换到世界空间坐标。这个在顶点着色器中很容易完成,所以我们声明一个输出变量,并计算它的世界空间坐标:

out vec3 FragPos;  
out vec3 Normal;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = aNormal;
}

在片段着色器中添加相应的输入变量:

in vec3 FragPos;

我们希望确保所有相关向量最后都转换为单位向量,所以我们把法线和最终的方向向量都进行标准化:

vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);

下一步,我们对norm和lightDir向量进行点乘,计算光源对当前片段实际的漫发射影响。结果值再乘以光的颜色,得到漫反射分量。两个向量之间的角度越大,漫反射分量就会越小:

float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

如果两个向量之间的角度大于90度,点乘的结果就会变成负数,这样会导致漫反射分量变为负数。为此,我们使用max函数返回两个参数之间较大的参数,从而保证漫反射分量不会变成负数。现在我们有了环境光分量和漫反射分量,我们把它们相加,然后把结果乘以物体的颜色,来获得片段最后的输出颜色。

vec3 result = (ambient + diffuse) * objectColor;
FragColor = vec4(result, 1.0);

代码

core.vs
#version 330 core
layout(location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout(location=2) in vec3 normal;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 projection;

out vec3 outColor;
out vec3 Normal;//varing vec3 Normal;
out vec3 FragPos;
void main()
{
	gl_Position = projection * view * transform * vec4(position,1.0f);
	outColor=color;
	Normal=mat3(transpose(inverse(transform)))*normal;
	FragPos=vec3(transform*vec4(position,1.0f));
}

core.fs
#version 330 core
in vec3 outColor;
in vec3 Normal;
in vec3 FragPos;
out vec4 color;

uniform vec3 LightPos;
uniform vec3 ViewPos;
void main()
{
	color = vec4(outColor,1.0f);//vec4(1.0f,0.0f,0.0f, 1.0f);
	//ambient
	vec3 ambient=0.3f*color.rgb;

	//diffuse
	vec3 norm=normalize(Normal);
	vec3 lightDir=normalize(LightPos-FragPos);
	float diff=0.6f*max(dot(norm,lightDir),0.0f);
	vec3 diffuse=diff*color.rgb;

	//specular
	vec3 viewDir=normalize(ViewPos-FragPos);//视角方向
	vec3 halfAngle=normalize(viewDir+lightDir);
	float spec=3.0f*pow(max(dot(norm,halfAngle),0.0f),64.0f);
	vec3 specular=spec*color.rgb;

	color=vec4(ambient+diffuse+specular,1.0f);

}
light.vs
#version 330 core
layout(location = 0) in vec3 position;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 projection;

void main()
{
gl_Position = projection * view * transform * vec4(position,1.0f);
}
light.fs
#version 330 core
out vec4 color;
void main()
{
color = vec4(1.0f,1.0f,1.0f,1.0f);
}
Camera.h
#pragma once
#include<vector>
#define GLFW_STATIC
#include<GL/glew.h>

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

enum Camera_Movement
{
	FOWARD,
	BACKWARD,
	LEFT,
	RIGHT
};

//6个自由度

const GLfloat YAW = -90.0f;//
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 6.0f;
const GLfloat SENSITIVITY = 0.25f;//灵敏度
const GLfloat ZOOM = 45.0f;

class Camera
{
public:
	Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f),
		GLfloat yaw = YAW, GLfloat pitch = PITCH):front(glm::vec3(0.0f, 0.0f, -1.0f)), movementSpeed(SPEED),
		mouseSensitivity(SENSITIVITY), zoom(ZOOM)
	{
		this->position = position;
		this->worldUp = up;
		this->yaw = yaw;
		this->pitch = pitch;
		this->updateCameraVectors();
	}
	Camera(GLfloat posX,GLfloat posY,GLfloat posZ,GLfloat upX,GLfloat upY,GLfloat upZ,
		GLfloat yaw = YAW, GLfloat pitch = PITCH) :front(glm::vec3(0.0f, 0.0f, -1.0f)), movementSpeed(SPEED),
		mouseSensitivity(SENSITIVITY), zoom(ZOOM)
	{
		this->position = glm::vec3(posX,posY,posZ);
		this->worldUp = glm::vec3(upX,upY,upZ);
		this->yaw = yaw;
		this->pitch = pitch;
		this->updateCameraVectors();
	}
	void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)//时间控制速度
	{
		GLfloat velocity = this->movementSpeed * deltaTime;

		if (direction == FOWARD) {
			this->position += this->front * velocity;
		}
		if (direction == BACKWARD) {
			this->position -= this->front * velocity;
		}
		if (direction == LEFT) {
			this->position -= this->right * velocity;
		}
		if (direction == RIGHT) {
			this->position += this->right * velocity;
		}
	}
	void ProcessMouseMovement(GLfloat xOffset,GLfloat yOffset)
	{
		xOffset *= this->mouseSensitivity;
		yOffset *= this->mouseSensitivity;

		this->yaw += xOffset;
		this->pitch += yOffset;

		this->updateCameraVectors();
	}
	void ProcessScroll(GLfloat yOffset)
	{
		this->zoom += yOffset;
	}
	GLfloat GetZoom()
	{
		return this->zoom;
	}
	glm::mat4 GetViewMatrix()
	{//视角矩阵
		return glm::lookAt(this->position, this->position + this->front, this->up);
	}
	glm::vec3 GetPosition()
	{
		return this->position;
	}
private:
	GLfloat yaw;
	GLfloat pitch;
	GLfloat movementSpeed;
	GLfloat mouseSensitivity;
	GLfloat zoom;

	glm::vec3 position;
	glm::vec3 front;
	glm::vec3 up;
	glm::vec3 right;
	glm::vec3 worldUp;
	void updateCameraVectors()
	{
		//相机的位置和朝向(前、上、右)
		glm::vec3 front;
		front.x = cos(glm::radians(this->pitch)) * cos(glm::radians(this->yaw));
		front.y = sin(glm::radians(this->pitch));
		front.z = cos(glm::radians(this->pitch)) * sin(glm::radians(this->yaw));

		this->front = glm::normalize(front);
		//normalize取单位化
		this->right = glm::normalize(glm::cross(this->front, this->worldUp));
		this->up = glm::normalize(glm::cross(this->right, this->front));
	}
};
Light.h
#pragma once
#define GLEW_STATIC
#include<GL/glew.h>
GLfloat vertices_light[] = {
	//position			//color
		//back
		-0.5,-0.5f,-0.5f,  
		0.5f,-0.5f,-0.5f,   
		0.5f,0.5f,-0.5f,    
		0.5f,0.5f,-0.5f,    
		-0.5f,0.5f,-0.5f,   
		-0.5f,-0.5f,-0.5f,  
		//front
		-0.5,-0.5f,0.5f,   
		0.5f,-0.5f,0.5f,   
		0.5f,0.5f,0.5f,    
		0.5f,0.5f,0.5f,    
		-0.5f,0.5f,0.5f,   
		-0.5f,-0.5f,0.5f,  
		//left
		-0.5f,0.5f,0.5f,	
		-0.5f,0.5f,-0.5f,	
		-0.5f,-0.5f,-0.5f,	
		-0.5f,-0.5f,-0.5f,	
		-0.5f,-0.5f,0.5f,	
		-0.5f,0.5f,0.5f,	
		//right
		0.5f,0.5f,0.5f,		
		0.5f,0.5f,-0.5f,	
		0.5f,-0.5f,-0.5f,	
		0.5f,-0.5f,-0.5f,	
		0.5f,-0.5f,0.5f,	
		0.5f,0.5f,0.5f,		
		//bottom
		-0.5f,-0.5f,-0.5f,	
		0.5f,-0.5f,-0.5f,	
		0.5f,-0.5f,0.5f,	
		0.5f,-0.5f,0.5f,	
		-0.5f,-0.5f,0.5f,	
		-0.5f,-0.5f,-0.5f,	
		//up
		-0.5f,0.5f,-0.5f,	
		0.5f,0.5f,-0.5f,	
		0.5f,0.5f,0.5f,		
		0.5f,0.5f,0.5f,		
		-0.5f,0.5f,0.5f,	
		-0.5f,0.5f,-0.5f,	
};

class Light
{
public:
	Light()
	{
		glGenVertexArrays(1, &this->VAO);
		glGenBuffers(1, &this->VBO);
		glBindVertexArray(this->VAO);
		glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_light), vertices_light, GL_STATIC_DRAW);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);
	}
	void Draw(Shader & shader)
	{
		glBindVertexArray(this->VAO);
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);
	}
private:
	GLuint VAO, VBO;

};
Shader.h
#pragma once

#include <string.h>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>

class Shader
{
	GLuint vertex, fragment;
public:
	GLuint Program;
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
	{
		std::string vertexCode;
		std::string fragmentCode;
		std::ifstream vShaderFile;
		std::ifstream fShaderFile;

		vShaderFile.exceptions(std::ifstream::badbit);
		fShaderFile.exceptions(std::ifstream::badbit);

		try
		{
			vShaderFile.open(vertexPath);
			fShaderFile.open(fragmentPath);

			std::stringstream vShaderStream, fShaderStream;
			vShaderStream << vShaderFile.rdbuf();
			fShaderStream << fShaderFile.rdbuf();

			vShaderFile.close();
			fShaderFile.close();

			vertexCode = vShaderStream.str();
			fragmentCode = fShaderStream.str();

		}
		catch (std::ifstream::failure e)
		{
			std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
		}
		const GLchar* vShaderCode = vertexCode.c_str();
		const GLchar* fShaderCode = fragmentCode.c_str();

		//compile Shaders
		GLint success;
		GLchar infoLog[512];
		vertex = glCreateShader(GL_VERTEX_SHADER);
		glShaderSource(vertex, 1, &vShaderCode, NULL);
		glCompileShader(vertex);

		glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
		if (!success) {
			glGetShaderInfoLog(vertex, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"
				<< infoLog << std::endl;
		}

		fragment = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(fragment, 1, &fShaderCode, NULL);
		glCompileShader(fragment);

		glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
		if (!success) {
			glGetShaderInfoLog(fragment, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"
				<< infoLog << std::endl;
		}

		this ->Program = glCreateProgram();
		glAttachShader(this->Program, vertex);
		glAttachShader(this->Program, fragment);
		glLinkProgram(this->Program);

		glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
		if (!success) {
			glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
			std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n"
				<< infoLog << std::endl;
		}
	}
	~Shader() {
		glDetachShader(this->Program, vertex);
		glDetachShader(this->Program, fragment);
		glDeleteShader(vertex);
		glDeleteShader(fragment);
		glDeleteProgram(this->Program);
	}
	void Use()
	{
		glUseProgram(this->Program);
	}
};


main.cpp
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include<GLFW/glfw3.h>
#include "Shader.h"
#include "Camera.h"
#include "Light.h"
//GLM
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include<glm/gtx/rotate_vector.hpp>

const GLint WIDTH = 800, HEIGHT = 600;

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);

void MouseCallback(GLFWwindow* window, double xPos, double yPos);
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffset);
void DoMovement();

GLfloat lastX = 0.0f;
GLfloat lastY = 0.0f;
bool firstMouse = true;

bool keys[1024];

Camera camera(glm::vec3(0.0f, 0.0f, 2.0f));
GLfloat deltaTime = 0.0f;
GLfloat lastTime = 0.0f;

glm::vec3 lightPos = glm::vec3(0.0f, 0.0f, 0.0f);//记录每次变化后,光源所在位置

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
	int screenWidth, screenHeight;
	glfwGetFramebufferSize(window, &screenWidth, &screenHeight);

	if (window == nullptr) {
		std::cout << "Failed to create GLFW window" <<
			std::endl;
		glfwTerminate();
		return  -1;
	}

	glfwMakeContextCurrent(window);

	glfwSetKeyCallback(window, KeyCallback);
	glfwSetCursorPosCallback(window, MouseCallback);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetScrollCallback(window, ScrollCallback);

	glewExperimental = GL_TRUE;

	if (glewInit() != GLEW_OK) {
		std::cout << "Failed to initialize GLEW" <<
			std::endl;
		glfwTerminate();
		return -1;
	}

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	//允许深度测试
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);//深度信息小的覆盖信息大的

	Shader shader = Shader("res/shaders/core.vs", "res/shaders/core.fs");
	Shader lightShader = Shader("res/shaders/light.vs", "res/shaders/light.fs");
	//Cube
	GLfloat vertices[] =
	{
		//position			//color          //法向量
		//back
		-0.5,-0.5f,-0.5f,   1.0f,0.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,-1.0f,
		0.5f,0.5f,-0.5f,    1.0f,0.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,-1.0f,
		-0.5f,0.5f,-0.5f,   1.0f,0.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,-1.0f,
		//front
		-0.5,-0.5f,0.5f,   0.0f,1.0f,0.0f,    0.0f,0.0f,1.0f,
		0.5f,-0.5f,0.5f,   0.0f,1.0f,0.0f,	  0.0f,0.0f,1.0f,
		0.5f,0.5f,0.5f,    0.0f,1.0f,0.0f,	  0.0f,0.0f,1.0f,
		0.5f,0.5f,0.5f,    0.0f,1.0f,0.0f,	  0.0f,0.0f,1.0f,
		-0.5f,0.5f,0.5f,   0.0f,1.0f,0.0f,	  0.0f,0.0f,1.0f,
		-0.5f,-0.5f,0.5f,  0.0f,1.0f,0.0f,	  0.0f,0.0f,1.0f,
		//left
		-0.5f,0.5f,0.5f,	0.0f,0.0f,1.0f,  -1.0f,0.0f,0.0f,
		-0.5f,0.5f,-0.5f,	0.0f,0.0f,1.0f,	 -1.0f,0.0f,0.0f,
		-0.5f,-0.5f,-0.5f,	0.0f,0.0f,1.0f,	 -1.0f,0.0f,0.0f,
		-0.5f,-0.5f,-0.5f,	0.0f,0.0f,1.0f,	 -1.0f,0.0f,0.0f,
		-0.5f,-0.5f,0.5f,	0.0f,0.0f,1.0f,	 -1.0f,0.0f,0.0f,
		-0.5f,0.5f,0.5f,	0.0f,0.0f,1.0f,	 -1.0f,0.0f,0.0f,
		//right
		0.5f,0.5f,0.5f,		0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		0.5f,0.5f,-0.5f,	0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		0.5f,-0.5f,-0.5f,	0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		0.5f,-0.5f,-0.5f,	0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		0.5f,-0.5f,0.5f,	0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		0.5f,0.5f,0.5f,		0.0f,1.0f,1.0f,   1.0f,0.0f,0.0f,
		//bottom
		-0.5f,-0.5f,-0.5f,	1.0f,0.0f,1.0f,   0.0f,-1.0f,0.0f,
		0.5f,-0.5f,-0.5f,	1.0f,0.0f,1.0f,	  0.0f,-1.0f,0.0f,
		0.5f,-0.5f,0.5f,	1.0f,0.0f,1.0f,	  0.0f,-1.0f,0.0f,
		0.5f,-0.5f,0.5f,	1.0f,0.0f,1.0f,	  0.0f,-1.0f,0.0f,
		-0.5f,-0.5f,0.5f,	1.0f,0.0f,1.0f,	  0.0f,-1.0f,0.0f,
		-0.5f,-0.5f,-0.5f,	1.0f,0.0f,1.0f,	  0.0f,-1.0f,0.0f,
		//up
		-0.5f,0.5f,-0.5f,	1.0f,1.0f,0.0f,   0.0f,1.0f,0.0f,
		0.5f,0.5f,-0.5f,	1.0f,1.0f,0.0f,	  0.0f,1.0f,0.0f,
		0.5f,0.5f,0.5f,		1.0f,1.0f,0.0f,	  0.0f,1.0f,0.0f,
		0.5f,0.5f,0.5f,		1.0f,1.0f,0.0f,	  0.0f,1.0f,0.0f,
		-0.5f,0.5f,0.5f,	1.0f,1.0f,0.0f,	  0.0f,1.0f,0.0f,
		-0.5f,0.5f,-0.5f,	1.0f,1.0f,0.0f,	  0.0f,1.0f,0.0f,
	};

	GLuint VAO, VBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	Light lightModel = Light();

	while (!glfwWindowShouldClose(window)) {
		GLfloat currentTime = glfwGetTime();
		deltaTime = currentTime - lastTime;
		lastTime = currentTime;

		glViewport(0, 0, screenWidth, screenHeight);
		glfwPollEvents();
		DoMovement();//在PollEvents后响应
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//用到都要初始化
		
		glm::mat4 view = camera.GetViewMatrix();

		glm::mat4 projection = glm::perspective(glm::radians(camera.GetZoom()),
			static_cast<GLfloat>(screenWidth) / static_cast<GLfloat>(screenHeight), 0.1f, 100.0f);

		GLuint viewLoc = glGetUniformLocation(shader.Program, "view");
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

		GLuint projectionLoc = glGetUniformLocation(shader.Program, "projection");
		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

		glm::mat4 transform = glm::mat4(1.0f);

		//平移
		transform = glm::translate(transform, glm::vec3(0.0f, 0.4f, 0.0f));
		//旋转
		//transform = glm::rotate(transform, glm::radians(20.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));
		//缩放
		transform = glm::scale(transform, glm::vec3(0.5f, 0.5f, 0.5f));



		GLuint transLoc = glGetUniformLocation(shader.Program, "transform");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));

		

		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);

		lightShader.Use();
		viewLoc = glGetUniformLocation(lightShader.Program, "view");
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

		projectionLoc = glGetUniformLocation(lightShader.Program, "projection");
		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

		transform = glm::mat4(1.0f);
		lightPos = glm::vec3(0.0f, 2.0f, 0.0f);
		lightPos = glm::rotate(lightPos, glm::radians(20.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));

		//transform = glm::rotate(transform, glm::radians(20.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));
		//transform = glm::translate(transform, glm::vec3(0.0f, 2.0f, 0.0f));
		transform = glm::translate(transform, lightPos);

		transform = glm::scale(transform, glm::vec3(0.1f, 0.1f, 0.1f));
		transLoc = glGetUniformLocation(lightShader.Program, "transform");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));

		lightModel.Draw(lightShader);
		shader.Use();
		viewLoc = glGetUniformLocation(shader.Program, "view");
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

		projectionLoc = glGetUniformLocation(shader.Program, "projection");
		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

		transform = glm::mat4(1.0f);

		//平移
		transform = glm::translate(transform, glm::vec3(0.0f, 0.4f, 0.0f));
		//旋转
	//	transform = glm::rotate(transform, glm::radians(20.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));
		//缩放
		transform = glm::scale(transform, glm::vec3(0.5f, 0.5f, 0.5f));



		transLoc = glGetUniformLocation(shader.Program, "transform");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));

		glUniform3f(glGetUniformLocation(shader.Program, "LightPos"), lightPos.x, lightPos.y, lightPos.z);
		glUniform3f(glGetUniformLocation(shader.Program, "ViewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);

		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);

		glfwSwapBuffers(window);
	}
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glfwTerminate();
	return 0;
}

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
	{
		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 MouseCallback(GLFWwindow* window, double xPos, double yPos)
{
	if (firstMouse) {
		lastX = xPos;
		lastY = yPos;
		firstMouse = false;
	}
	GLfloat xOffset = xPos - lastX;
	GLfloat yOffset = lastY - yPos;

	lastX = xPos;
	lastY = yPos;

	camera.ProcessMouseMovement(xOffset, yOffset);
}
void DoMovement()
{
	if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP]) {
		//up
		camera.ProcessKeyboard(FOWARD, deltaTime);
	}
	if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN]) {
		//down
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	}
	if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT]) {
		//left
		camera.ProcessKeyboard(LEFT, deltaTime);
	}
	if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT]) {
		//right
		camera.ProcessKeyboard(RIGHT, deltaTime);
	}
}
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffset)
{
	camera.ProcessScroll(yOffset);
}

运行结果

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值