http://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/06%20Multiple%20lights/
main.cpp
//main.cpp
#include
#define GLEW_STATIC
#include
#include
#include "Shader.h"
#include "Camera.h"
#include
#include
#include
#include
#include
#include "Shader.h"
#pragma comment(lib, "./SOIL.lib")
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glew32s.lib")
#pragma comment (lib, "glfw3.lib")
#pragma comment (lib, "glfw3dll.lib")
#pragma comment (lib, "glew32mxs.lib")
void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos);
void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset);
void do_movement();
const GLuint WIDTH = 800, HEIGHT = 600;
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool keys[1024];
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 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_RESIZABLE, GL_FALSE);
GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGHT, "MultipleLight", nullptr, nullptr);
glfwMakeContextCurrent(pWnd);
glfwSetKeyCallback(pWnd, key_callback);
glfwSetCursorPosCallback(pWnd, mouse_callback);
glfwSetScrollCallback(pWnd, scroll_callback);
// 鼠标指针隐藏
//glfwSetInputMode(pWnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glewExperimental = GL_TRUE;
glewInit();
glViewport(0, 0, WIDTH, HEIGHT);
glEnable(GL_DEPTH_TEST);
// Shader 处理 箱子 以及 灯光
Shader lightingObjShader("./obj_vertex.vs", "./obj_fragement.fs");
Shader lampShader("./lamp_vertex.vs", "./lamp_fragement.fs");
// 点数据
GLfloat vertices[] = { // 位置3 向量3 纹理2
// 背面
-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
};
// 箱子位置
glm::vec3 objPos[] = {
glm::vec3(-3.0f, -1.0f, -5.0f), glm::vec3(2.0f, 5.0f, -1.0f),
glm::vec3(-1.5f, -2.2f, -2.5f), glm::vec3(0.0f, -2.0f, -5.3f),
glm::vec3(2.4f, -0.4f, -3.5f), glm::vec3(-1.7f, 0.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)
};
GLuint objVAO, VBO;
glGenVertexArrays(1, &objVAO);
// 光照物体
glBindVertexArray(objVAO); // --- Begin
{
// 顶点数据复至GPU中
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
{
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 位置索引 传至Shader的
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);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0); // --- End
// 灯泡 (只需要用到一部分坐标点数据,用于绘制一个立方体即可)
GLuint lampVAO, lampVBO;
glGenVertexArrays(1, &lampVAO);
glBindVertexArray(lampVAO);
{
//glGenBuffers(1, &lampVBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
{
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
// 纹理1 木箱纹理贴图 --
// 1. 加载图片 木箱图片
int nTextureW = 0, nTextureH = 0;
unsigned char* pChImg = nullptr;
pChImg = SOIL_load_image("texture.png", &nTextureW, &nTextureH, 0, SOIL_LOAD_RGB);
// 2. 纹理设置
GLuint diffuseMap;
glGenTextures(1, &diffuseMap);
{
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureW, nTextureH, 0, GL_RGB, GL_UNSIGNED_BYTE, pChImg);
glGenerateMipmap(GL_TEXTURE_2D);
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);
SOIL_free_image_data(pChImg); // 释放内存
// 纹理2 木箱边框反射贴图 --
// 1. 加载图片 木箱边框图片
pChImg = SOIL_load_image("texture_specular.png", &nTextureW, &nTextureH, 0, SOIL_LOAD_RGB);
// 2. 纹理设置
GLuint specularMap;
glGenTextures(1, &specularMap);
glBindTexture(GL_TEXTURE_2D, specularMap);
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureW, nTextureH, 0, GL_RGB, GL_UNSIGNED_BYTE, pChImg);
glGenerateMipmap(GL_TEXTURE_2D);
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);
SOIL_free_image_data(pChImg);
// 设置Shader中的材质属性
lightingObjShader.useShaderPrograme();
glUniform1i(glGetUniformLocation(lightingObjShader.getPrograme(), "material.diffuse"), 0);
glUniform1i(glGetUniformLocation(lightingObjShader.getPrograme(), "material.specular"), 1);
GLuint nCurrentTime = glfwGetTime();
GLuint nLastTime = glfwGetTime();
GLuint nFPS = 0;
glm::mat4 view;
glm::mat4 model;
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 只绘边框
while (!glfwWindowShouldClose(pWnd))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
do_movement();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lightingObjShader.useShaderPrograme();
GLint viewPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "viewPos");
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
// 设置Shader中的材质属性
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "material.shininess"), 4.0f);
// Directional light
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.direction"), -0.2f, -1.0f, -0.3f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.specular"), 0.5f, 0.5f, 0.5f);
// Point light 1
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].constant"), 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].linear"), 0.09);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].quadratic"), 0.032);
// Point light 2
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].constant"), 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].linear"), 0.09);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].quadratic"), 0.032);
// Point light 3
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].constant"), 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].linear"), 0.09);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].quadratic"), 0.032);
// Point light 4
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].constant"), 1.0f);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].linear"), 0.09);
glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].quadratic"), 0.032);
GLint modelLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "model");
GLint viewLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "view");
GLint projLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "projection");
view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
//// 设置光源参数
//GLint lightPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.position");
//GLint lightDirLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.direction");
//GLint lightPosCutoffLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.cutOff");
//GLint lightSpotOuterCutOffLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.outerCutOff"); // add 外圆
//GLint viewPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "viewPos");
//glUniform3f(lightPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
//glUniform3f(lightDirLoc, camera.Front.x, camera.Front.y, camera.Front.z);
//glUniform1f(lightPosCutoffLoc, glm::cos(glm::radians(12.5))); // 聚光灯半径 内圆
//glUniform1f(lightSpotOuterCutOffLoc, glm::cos(glm::radians(17.5f))); // add 聚光灯 外圆 内圆至外圆逐渐变暗
//glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
//// 设置Shader中的灯光属性
//glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.ambient"), 0.1f, 0.1f, 0.1f);
//glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.diffuse"), 0.8f, 0.8f, 0.8f);
//glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.specular"), 1.0f, 1.0f, 1.0f);
//glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.constant"), 1.0f);
//glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.linear"), 0.09f);
//glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.quadratic"), 0.032f);
//
//// 设置Shader中的材质属性
//glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "material.shininess"), 4.0f);
//// 摄像机设置
//view = camera.GetViewMatrix();
//glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
//GLint modelLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "model");
//GLint viewLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "view");
//GLint projLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "projection");
//glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// 绑定漫反射贴图
glActiveTexture(GL_TEXTURE0); // 箱子纹理
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glActiveTexture(GL_TEXTURE1); // 箱子边框的镜面反射纹理
glBindTexture(GL_TEXTURE_2D, specularMap);
// 绘制箱子 -------------------
glBindVertexArray(objVAO); // 绑定箱子的顶点数据进行操作
for (GLuint i = 0; i < 10; i++)
{
model = glm::mat4();
model = glm::translate(model, objPos[i]);
GLfloat angle = glfwGetTime();
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);
}
for (GLuint i = 0; i < 10; i++)
{
model = glm::mat4();
model = glm::translate(model, objPos[i] + objPos[i]);
GLfloat angle = glfwGetTime();
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);
}
for (GLuint i = 0; i < 10; i++)
{
model = glm::mat4();
model = glm::translate(model, objPos[i] + objPos[i] + objPos[i]);
GLfloat angle = glfwGetTime();
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.useShaderPrograme();
modelLoc = glGetUniformLocation(lampShader.getPrograme(), "model");
viewLoc = glGetUniformLocation(lampShader.getPrograme(), "view");
projLoc = glGetUniformLocation(lampShader.getPrograme(), "projection");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
//model = glm::mat4();
//model = glm::translate(model, lightPos);
//model = glm::scale(model, glm::vec3(0.2f)); // 缩小
//glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(lampVAO); // 绑定灯泡的顶点数据进行操作
{
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(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
}
glBindVertexArray(0); // 解绑
glfwSwapBuffers(pWnd);
// -----------------------------------------------
nLastTime = glfwGetTime();
nFPS++;
if (nLastTime - nCurrentTime > 1)
{
std::cout << "当前帧率:" << nFPS << std::endl;
nFPS = 0;
nCurrentTime = nLastTime;
}
}
glfwTerminate();
return 0;
}
void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(pWnd, 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()
{
if (keys[GLFW_KEY_W])
camera.ProcessKeyboard(FORWARD, deltaTime);
if (keys[GLFW_KEY_S])
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (keys[GLFW_KEY_A])
camera.ProcessKeyboard(LEFT, deltaTime);
if (keys[GLFW_KEY_D])
camera.ProcessKeyboard(RIGHT, deltaTime);
}
bool firstMouse = true;
void mouse_callback(GLFWwindow* pWnd, 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 scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
}
Camera.h
//Camera.h
#pragma once
// Std. Includes
#include
// GL Includes
#include
#include
#include
// 摄像机移动方向 程序中用WSAD控制
enum Camera_Movement {
FORWARD,
BACKWARD,
LEFT,
RIGHT
};
// Default camera values
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f;
class Camera
{
public:
// Camera Attributes
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Up;
glm::vec3 Right;
glm::vec3 WorldUp;
// Eular Angles
GLfloat Yaw;
GLfloat Pitch;
// Camera options
GLfloat MovementSpeed;
GLfloat MouseSensitivity;
GLfloat Zoom;
// Constructor with vectors
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(SENSITIVTY), Zoom(ZOOM)
{
this->Position = position;
this->WorldUp = up;
this->Yaw = yaw;
this->Pitch = pitch;
this->updateCameraVectors();
}
// Constructor with scalar values
Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY,
GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
{
this->Position = glm::vec3(posX, posY, posZ);
this->WorldUp = glm::vec3(upX, upY, upZ);
this->Yaw = yaw;
this->Pitch = pitch;
this->updateCameraVectors();
}
// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
glm::mat4 GetViewMatrix()
{
return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
}
// 按键处理
void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
{
GLfloat velocity = this->MovementSpeed * deltaTime;
if (direction == FORWARD)
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,
GLboolean constrainPitch = true)
{
xoffset *= this->MouseSensitivity;
yoffset *= this->MouseSensitivity;
this->Yaw += xoffset;
this->Pitch += yoffset;
// Make sure that when pitch is out of bounds, screen doesn't get flipped
if (constrainPitch)
{
if (this->Pitch > 89.0f)
this->Pitch = 89.0f;
if (this->Pitch < -89.0f)
this->Pitch = -89.0f;
}
// Update Front, Right and Up Vectors using the updated Eular angles
this->updateCameraVectors();
}
// Processes input received from a mouse scroll-wheel event.
// Only requires input on the vertical wheel-axis
void ProcessMouseScroll(GLfloat yoffset)
{
if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
this->Zoom -= yoffset;
if (this->Zoom <= 1.0f)
this->Zoom = 1.0f;
if (this->Zoom >= 45.0f)
this->Zoom = 45.0f;
}
private:
// Calculates the front vector from the Camera's (updated) Eular Angles
void updateCameraVectors()
{
// Calculate the new Front vector
glm::vec3 front;
front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
front.y = sin(glm::radians(this->Pitch));
front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
this->Front = glm::normalize(front);
// Also re-calculate the Right and Up vector
// Normalize the vectors, because their length gets closer to 0 the more
// you look up or down which results in slower movement.
this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));
this->Up = glm::normalize(glm::cross(this->Right, this->Front));
}
};
Shader.h
//Shader.h
#pragma once
#ifndef TEXTURE_SHADER_H_
#define TEXTURE_SHADER_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class Shader
{
public:
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
~Shader();
public:
void useShaderPrograme();
GLuint getPrograme() {
return this->m_nProgram;
}
private:
GLuint m_nProgram;
};
Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
std::string vertexCode;
std::string fragmentCode;
std::ifstream vertexShaderF;
std::ifstream fragementShaderF;
vertexShaderF.exceptions(std::ifstream::badbit);
fragementShaderF.exceptions(std::ifstream::badbit);
try
{
vertexShaderF.open(vertexPath); // 打开文件
fragementShaderF.open(fragmentPath);
std::stringstream vertexShaderStream, fragementShaderStream;
vertexShaderStream << vertexShaderF.rdbuf(); // 读取文件至stringstream中
fragementShaderStream << fragementShaderF.rdbuf();
vertexShaderF.close();
fragementShaderF.close();
vertexCode = vertexShaderStream.str(); // 转换成string类型
fragmentCode = fragementShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;
}
const GLchar* pVertexCode = vertexCode.c_str(); // string 转 char*
const GLchar* pFragementCode = fragmentCode.c_str();
GLuint nVertexShader, nFragementShader;
GLint nRes = 0;
GLchar chLogInfo[512] = { '\0' };
// 创建顶点着色器
nVertexShader = glCreateShader(GL_VERTEX_SHADER);
// 将顶点着色程序的源代码字符数组绑定到顶点着色器对象
glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);
glCompileShader(nVertexShader); // compile shader 编译着色器
// 获取编译结果
glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;
}
// 创建片断着色器
nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);
// 将片段着色程序的源代码字符数组绑定到片段着色器对象
glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);
glCompileShader(nFragementShader);
glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);
if (!nRes)
{
glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);
std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;
}
this->m_nProgram = glCreateProgram(); // 创建GLSL程序
glAttachShader(this->m_nProgram, nVertexShader); // 绑定shader到program
glAttachShader(this->m_nProgram, nFragementShader);
// glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令
glLinkProgram(this->m_nProgram); // 链接
glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);
if (!nRes)
{
glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);
std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;
}
glDeleteShader(nVertexShader);
glDeleteShader(nFragementShader);
}
Shader::~Shader()
{
}
#include
#include
#include
void Shader::useShaderPrograme()
{
glUseProgram(this->m_nProgram); // 使用porgram
}
#endif
lamp_vertex.vs
// 灯泡顶点着色器
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
// 灯泡只需设置位置
gl_Position = projection * view * model * vec4(position, 1.0f);
}
lamp_fragement.fs
// 灯泡片断着色器
#version 330 core
out vec4 color;
in vec3 IN_Normal;
void main()
{
color = vec4(1.0f); // 灯泡为白色
}
obj_vertex.vs
// 箱子顶点着色器
#version 330 core
// 位置顶点 及 位置顶点的向量
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords; // 纹理坐标
out vec3 IN_ObjPos; // 顶点位置
out vec3 IN_Normal; // 法向量
out vec2 IN_TexCoords; // 纹理
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
// 顶点变换到世界空间坐标 把顶点位置属性乘以模型矩阵
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
IN_ObjPos = vec3(model * vec4(position, 1.0f));
IN_Normal = mat3(transpose(inverse(model))) * normal;
IN_TexCoords = texCoords; // 纹理输出至片断着色器
}
obj_fragement.fs
// 箱子 片断着色器
#version 330 core
// 材质结构体
struct Material
{
sampler2D diffuse; // 漫反射光照下物体的颜色
sampler2D specular; // 物体受到的镜面光照的影响的颜色
float shininess; // 高光的散射/半径
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct Light {
vec3 position; // 光源位置
//vec3 direction;
vec3 ambient; // 环境光
vec3 diffuse; // 漫反射光
vec3 specular; // 镜面光
// 计算衰减值
float constant; // 常数项Kc
float linear; // 一次项Kl
float quadratic; // 二次项KqKq
//float cutOff; // 内圆切光角
//float outerCutOff; // add 外圆切光角
};
in vec3 IN_ObjPos; // 顶点位置
in vec3 IN_Normal; // 法向量
in vec2 IN_TexCoords; // 纹理
out vec4 color;
#define NR_POINT_LIGHTS 4
uniform vec3 viewPos;
uniform DirLight dirLight; //
uniform Material material;
uniform Light lights[NR_POINT_LIGHTS]; // 光源数组
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
vec3 normal = normalize(IN_Normal) ;
vec3 viewDir = normalize(viewPos - IN_ObjPos);
vec3 result = CalcDirLight(dirLight, normal, viewDir);
for(int i = 0; i< NR_POINT_LIGHTS; i++)
{
result += CalcPointLight(lights[i], normal, IN_ObjPos, 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, IN_TexCoords));// 环境光
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, IN_TexCoords));// 漫反射光
vec3 specular = light.specular * spec * vec3(texture(material.specular, IN_TexCoords));// 镜面光
return vec3(ambient + diffuse + specular);
}
vec3 CalcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - IN_ObjPos); // 光源和片段位置之间的方向向量
float diff = max(dot(normal, lightDir), 0.0); // 点乘, 来计算光对当前片段的实际的散射影响 大于90度, 点乘的结果就会变成负数, max 函数返回两个参数之间较大的参数, 从而保证散射因子不会变成负数。
vec3 reflectDir = reflect(-lightDir, normal); // 计算反射向量和视线方向的角度, 如果之间的角度越小, 那么镜面光的作用就会越大
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * vec3(texture(material.diffuse, IN_TexCoords));// 环境光
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, IN_TexCoords));// 漫反射光
vec3 specular = light.specular * spec * vec3(texture(material.specular, IN_TexCoords));// 镜面光
float distance = length(light.position - IN_ObjPos); // 光源到物体的距离
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); // 衰减因子
ambient *= attenuation; // 所有的光线都与衰减因子相乘
diffuse *= attenuation;
specular *= attenuation;
return vec3(ambient + diffuse + specular); // 最后的输出颜色。
}
源码下载: VS2015http://download.csdn.net/detail/yulinxx/9858107