我们在前面的教程中已经学习了许多关于OpenGL 光照的知识,其中包括冯氏照明模型(Phong shading)、光照材质(Materials)、光照图(Lighting maps)以及各种投光物(Light casters)。本教程将结合上述所学的知识,创建一个包含六个光源的场景。我们将模拟一个类似阳光的平行光(Directional light)和4个定点光(Point lights)以及一个手电筒(Flashlight).
要在场景中使用多光源我们需要封装一些GLSL函数用来计算光照。如果我们对每个光源都去写一遍光照计算的代码,这将是一件令人恶心的事情,并且这些放在main函数中的代码将难以理解,所以我们将一些操作封装为函数。
GLSL中的函数与C语言的非常相似,它需要一个函数名、一个返回值类型。并且在调用前必须提前声明。接下来我们将为下面的每一种光照来写一个函数。
当我们在场景中使用多个光源时一般使用以下途径:创建一个代表输出颜色的向量。每一个光源都对输出颜色贡献一些颜色。因此,场景中的每个光源将进行独立运算,并且运算结果都对最终的输出颜色有一定影响。下面是使用这种方式进行多光源运算的一般结构:
out vec4 color;
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);
}
实践
Shader
#define STRINGIZE(x) #x
#define SHADER(shader) STRINGIZE(shader)
//顶点着色器程序
static char *myMyMultipleLightSourcesVertexShaderStr = SHADER(
\#version 330 core\n
layout (location = 0) in vec3 position; //顶点数据源输入
layout (location = 1) in vec3 normal; //法向量
layout (location = 2) in vec2 texCoords; //纹理数据源输入(2D)
uniform mat4 myProjection;//投影矩阵
uniform mat4 myView;//观察矩阵
uniform mat4 myModel;//模型矩阵
out vec3 Normal;//法线向量
out vec3 FragPos;//片段位置
out vec2 TexCoords;//把片元着色器的纹理从这里输出
void main()
{
gl_Position = myProjection * myView * myModel * vec4(position, 1.0f);
Normal = normal;
FragPos = vec3(myModel * vec4(position, 1.0f) );
TexCoords = texCoords;
}
);
//片元着色器程序
static char *myMyMultipleLightSourcesFragmentShaderSrc = SHADER(
\#version 330 core\n
//材质
struct Material {
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;//镜面反射光照
};
#define NR_POINT_LIGHTS 4
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;//材质
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
out vec4 color;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);//定向光照颜色
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);//点光源颜色
void main()
{
// Properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// == ======================================
//我们的照明分为3个阶段:定向,点光源和可选的手电筒,对于每个阶段,都定义了一个计算功能,用于计算每个灯的相应颜色。
//在main()函数中,我们获取所有计算出的颜色,并将其求和为该片段的最终颜色。
// == ======================================
// Phase 1: 定向光源
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// Phase 2: 计算点光源
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
// Phase 3: 聚光
// 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);
}
);
顶点数据
GLfloat myMultipleLightSourcesVertices[] = {
//顶点数据 法线 纹理坐标
-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, 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, 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, 0.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, 1.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, 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, 1.0f, 0.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, 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, 0.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, 1.0f, 0.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, 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, 0.0f, 0.0f,
};
程序
#include <iostream>
#include "MyMultipleLightSources.hpp"
#include "MyProgram.hpp"
#include "MyMultipleLightSourcesShader.h"
#include "MyMultipleLightSourcesVertices.h"
#include "glm.hpp"
#include "matrix_transform.hpp"
#include "type_ptr.hpp"
#include "MyCamera.h"
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_STATIC
#include "stb_image.h"
namespace MyMultipleLightSources {
// 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
Camera camera(glm::vec3(0.0f, 0.0f, 3.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.05f; // Time between current frame and last frame
GLfloat lastFrame = 0.05f; // Time of last frame
// 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 controls
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* 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 left
lastX = xpos;
lastY = ypos;
camera.ProcessMouseMovement(xoffset, yoffset);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
}
int runMyMultipleLightSourcesCube() {
int result = glfwInit();
if (result == GL_FALSE) {
printf("glfwInit 初始化失败");
return -1;
}
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, GLFW_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "My Opengl Window", NULL, NULL);
if(!window) {
printf("window 创建失败");
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
//设置(键盘鼠标)输入事件
//此函数设置指定窗口的按键回调,当按下,重复或释放按键时调用该回调。
glfwSetKeyCallback(window, key_callback);
//此函数设置指定窗口的光标位置回调,在移动光标时调用该回调。 回调提供了相对于窗口内容区域左上角的屏幕坐标位置。
glfwSetCursorPosCallback(window, mouse_callback);
//此函数设置指定窗口的滚动回调,在使用滚动设备(例如鼠标滚轮或触摸板的滚动区域)时调用此回调。
//滚动回调接收所有滚动输入,例如来自鼠标滚轮或触摸板滚动区域的滚动输入。
glfwSetScrollCallback(window, scroll_callback);
//glfwSetInputMode
//光标模式值 : GLFW_CURSOR_DISABLED
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
//切换为纹理着色器程序
MyProgram myProgram = MyProgram(myMyMultipleLightSourcesVertexShaderStr, myMyMultipleLightSourcesFragmentShaderSrc);
///
GLuint VBO , VAO ;
unsigned int squareIndicesCount = 0;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(myMultipleLightSourcesVertices), myMultipleLightSourcesVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(0 * sizeof(GLfloat)));
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);
//解绑VAO
glBindVertexArray(0);
squareIndicesCount = sizeof(myMultipleLightSourcesVertices)/(sizeof(myMultipleLightSourcesVertices[0]) * 8);
glEnable(GL_DEPTH_TEST);
//加载纹理
unsigned int diffuseCasters_texture;
unsigned char *diffuseCasters_data;
int diffuseCasters_width, diffuseCasters_height, diffuseCasters_nrChannels;
glGenTextures(1, &diffuseCasters_texture);
glBindTexture(GL_TEXTURE_2D, diffuseCasters_texture);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
diffuseCasters_data = stbi_load( "/Users/liliguang/Desktop/LearnOpengl/LearnOpenGl/LearnOpenGl/Demo/Common/ImgSources/box.png" , &diffuseCasters_width, &diffuseCasters_height, &diffuseCasters_nrChannels, 0);
if (diffuseCasters_data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, diffuseCasters_width, diffuseCasters_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, diffuseCasters_data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(diffuseCasters_data);
unsigned int specularCasters_texture;
unsigned char *specularCasters_data;
int specularCasters_width, specularCasters_height, specularCasters_nrChannels;
glGenTextures(1, &specularCasters_texture);
glBindTexture(GL_TEXTURE_2D, specularCasters_texture);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
specularCasters_data = stbi_load( "/Users/liliguang/Desktop/LearnOpengl/LearnOpenGl/LearnOpenGl/Demo/Common/ImgSources/box_specular.png" , &specularCasters_width, &specularCasters_height, &specularCasters_nrChannels, 0);
if (specularCasters_data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, specularCasters_width, specularCasters_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, specularCasters_data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(specularCasters_data);
//材质-光照贴图
glUseProgram(myProgram.program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseCasters_texture);
glUniform1i(glGetUniformLocation(myProgram.program, "material.diffuse"), 0);//环境贴图
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularCasters_texture);
glUniform1i(glGetUniformLocation(myProgram.program, "material.specular"), 1);//环境贴图
//Cube位置
glm::vec3 cubePositions[] = {
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, -1.0f, -1.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-2.8f, -1.0f, -2.3f),
glm::vec3( 2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 2.0f, -0.1f),
glm::vec3( 1.3f, -2.0f, -2.2f),
glm::vec3( 1.5f, 2.0f, -2.9f),
glm::vec3( 1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.2f)
};
int cubePositionsCount = sizeof(cubePositions)/(sizeof(cubePositions[0]));
//点光源位置
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)
};
//进行绘制
while(!glfwWindowShouldClose(window)){
glfwPollEvents();
do_movement();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//================================================
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
GLint myModelLoc = glGetUniformLocation(myProgram.program,"myModel");
GLint myViewLoc = glGetUniformLocation(myProgram.program,"myView");
GLint myProjectionLoc = glGetUniformLocation(myProgram.program,"myProjection");
projection = glm::perspective(glm::radians(90.0f), 1.0f, 0.01f, 100.f);//投影矩阵
glUniformMatrix4fv(myProjectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
view = camera.GetViewMatrix();
glUniform3f(myViewLoc, camera.Position.x, camera.Position.y, camera.Position.z);
glUniformMatrix4fv(myViewLoc, 1, GL_FALSE, glm::value_ptr(view));
glBindVertexArray(VAO);
//================================================
//光照
//================================================
//镜面反射半径
GLint matShineLoc = glGetUniformLocation(myProgram.program, "material.shininess");
glUniform1f(matShineLoc, 64.0f);
GLint viewPosLoc = glGetUniformLocation(myProgram.program, "viewPos");
glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
// 定向光源
glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.direction"), -0.2f, -1.0f, -0.3f);
glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
glUniform3f(glGetUniformLocation(myProgram.program, "dirLight.specular"), 0.5f, 0.5f, 0.5f);
// 点光源 1 红色
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].ambient"), 1.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].constant"), 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].linear"), 0.09);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[0].quadratic"), 0.032);
// 点光源 2 绿色
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].ambient"), 0.0f, 1.0f, 0.0f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].constant"), 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].linear"), 0.09);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[1].quadratic"), 0.032);
// 点光源 3 蓝色
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].ambient"), 0.0f, 0.0f, 1.0f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[2].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].constant"), 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].linear"), 0.09);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[2].quadratic"), 0.032);
// 点光源 4 灰
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].ambient"), 0.5f, 0.5f, 0.5f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(myProgram.program, "pointLights[3].specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].constant"), 1.0f);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].linear"), 0.09);
glUniform1f(glGetUniformLocation(myProgram.program, "pointLights[3].quadratic"), 0.032);
//================================================
for(GLuint i = 0; i < cubePositionsCount; i++)
{
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(myModelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, squareIndicesCount);
}
glBindVertexArray(0);
glfwSwapBuffers(window);
}
//程序销毁
glfwTerminate();
return 1;
}
}
网友评论