版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.12.24 |
前言
OpenGL 圖形庫(kù)項(xiàng)目中一直也沒用過胁孙,最近也想學(xué)著使用這個(gè)圖形庫(kù)痴柔,感覺還是很有意思裳涛,也就自然想著好好的總結(jié)一下,希望對(duì)大家能有所幫助迁筛。
1. OpenGL 圖形庫(kù)使用(一) —— 概念基礎(chǔ)
2. OpenGL 圖形庫(kù)使用(二) —— 渲染模式煤蚌、對(duì)象、擴(kuò)展和狀態(tài)機(jī)
3. OpenGL 圖形庫(kù)使用(三) —— 著色器细卧、數(shù)據(jù)類型與輸入輸出
4. OpenGL 圖形庫(kù)使用(四) —— Uniform及更多屬性
5. OpenGL 圖形庫(kù)使用(五) —— 紋理
6. OpenGL 圖形庫(kù)使用(六) —— 變換
7. OpenGL 圖形庫(kù)的使用(七)—— 坐標(biāo)系統(tǒng)之五種不同的坐標(biāo)系統(tǒng)(一)
8. OpenGL 圖形庫(kù)的使用(八)—— 坐標(biāo)系統(tǒng)之3D效果(二)
9. OpenGL 圖形庫(kù)的使用(九)—— 攝像機(jī)(一)
10. OpenGL 圖形庫(kù)的使用(十)—— 攝像機(jī)(二)
11. OpenGL 圖形庫(kù)的使用(十一)—— 光照之顏色
12. OpenGL 圖形庫(kù)的使用(十二)—— 光照之基礎(chǔ)光照
材質(zhì)
在現(xiàn)實(shí)世界里尉桩,每個(gè)物體會(huì)對(duì)光產(chǎn)生不同的反應(yīng)。比如說贪庙,鋼看起來通常會(huì)比陶瓷花瓶更閃閃發(fā)光蜘犁,木頭箱子也不會(huì)像鋼制箱子那樣對(duì)光產(chǎn)生很強(qiáng)的反射。每個(gè)物體對(duì)鏡面高光也有不同的反應(yīng)止邮。有些物體反射光的時(shí)候不會(huì)有太多的散射(Scatter)这橙,因而產(chǎn)生一個(gè)較小的高光點(diǎn),而有些物體則會(huì)散射很多导披,產(chǎn)生一個(gè)有著更大半徑的高光點(diǎn)屈扎。如果我們想要在OpenGL中模擬多種類型的物體,我們必須為每個(gè)物體分別定義一個(gè)材質(zhì)(Material)
屬性撩匕。
在上一節(jié)中助隧,我們指定了一個(gè)物體和光的顏色,以及結(jié)合環(huán)境光和鏡面強(qiáng)度分量,來定義物體的視覺輸出并村。當(dāng)描述一個(gè)物體的時(shí)候巍实,我們可以用這三個(gè)分量來定義一個(gè)材質(zhì)顏色(Material Color):環(huán)境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和鏡面光照(Specular Lighting)
哩牍。通過為每個(gè)分量指定一個(gè)顏色棚潦,我們就能夠?qū)ξ矬w的顏色輸出有著精細(xì)的控制了。現(xiàn)在膝昆,我們?cè)偬砑?code>反光度(Shininess)這個(gè)分量到上述的三個(gè)顏色中丸边,這就有我們需要的所有材質(zhì)屬性了:
#version 330 core
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material material;
在片段著色器中,我們創(chuàng)建一個(gè)結(jié)構(gòu)體(Struct)來儲(chǔ)存物體的材質(zhì)屬性荚孵。我們也可以把它們儲(chǔ)存為獨(dú)立的uniform值妹窖,但是作為一個(gè)結(jié)構(gòu)體來儲(chǔ)存會(huì)更有條理一些。我們首先定義結(jié)構(gòu)體的布局(Layout)
收叶,然后使用剛創(chuàng)建的結(jié)構(gòu)體為類型骄呼,簡(jiǎn)單地聲明一個(gè)uniform
變量。
你可以看到判没,我們?yōu)槊總€(gè)馮氏光照模型的分量都定義一個(gè)顏色向量蜓萄。ambient材質(zhì)
向量定義了在環(huán)境光照下這個(gè)物體反射得是什么顏色,通常這是和物體顏色相同的顏色澄峰。diffuse材質(zhì)
向量定義了在漫反射光照下物體的顏色嫉沽。(和環(huán)境光照一樣)漫反射顏色也要設(shè)置為我們需要的物體顏色。specular材質(zhì)
向量設(shè)置的是鏡面光照對(duì)物體的顏色影響(或者甚至可能反射一個(gè)物體特定的鏡面高光顏色)俏竞。最后绸硕,shininess
影響鏡面高光的散射/半徑。
這四個(gè)元素定義了一個(gè)物體的材質(zhì)魂毁,通過它們我們能夠模擬很多現(xiàn)實(shí)世界中的材質(zhì)玻佩。devernay.free.fr上的一個(gè)表格展示了幾種材質(zhì)屬性,它們模擬了現(xiàn)實(shí)世界中的真實(shí)材質(zhì)漱牵。下面的圖片展示了幾種現(xiàn)實(shí)世界的材質(zhì)對(duì)我們的立方體的影響:
可以看到夺蛇,通過正確地指定一個(gè)物體的材質(zhì)屬性疚漆,我們對(duì)這個(gè)物體的感知也就不同了酣胀。效果非常明顯,但是要想獲得更真實(shí)的效果娶聘,我們最終需要更加復(fù)雜的形狀闻镶,而不單單是一個(gè)立方體。在后面的教程中丸升,我們會(huì)討論更復(fù)雜的形狀铆农。
為一個(gè)物體賦予一款合適的材質(zhì)是非常困難的,這需要大量實(shí)驗(yàn)和豐富的經(jīng)驗(yàn),所以由于不合適的材質(zhì)而毀了物體的視覺質(zhì)量是件經(jīng)常發(fā)生的事墩剖。
讓我們?cè)谥髦袑?shí)現(xiàn)這樣的一個(gè)材質(zhì)系統(tǒng)猴凹。
設(shè)置材質(zhì)
我們?cè)谄沃髦袆?chuàng)建了一個(gè)材質(zhì)結(jié)構(gòu)體的uniform,所以下面我們希望修改一下光照的計(jì)算來順應(yīng)新的材質(zhì)屬性岭皂。由于所有材質(zhì)變量都儲(chǔ)存在結(jié)構(gòu)體中郊霎,我們可以從uniform
變量material
中訪問它們:
void main()
{
// 環(huán)境光
vec3 ambient = lightColor * material.ambient;
// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = lightColor * (diff * material.diffuse);
// 鏡面光
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = lightColor * (spec * material.specular);
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}
可以看到,我們現(xiàn)在在需要的地方訪問了材質(zhì)結(jié)構(gòu)體中的所有屬性爷绘,并且這次是根據(jù)材質(zhì)的顏色來計(jì)算最終的輸出顏色的书劝。物體的每個(gè)材質(zhì)屬性都乘上了它們對(duì)應(yīng)的光照分量。
我們現(xiàn)在可以在程序中設(shè)置適當(dāng)?shù)膗niform土至,對(duì)物體設(shè)置材質(zhì)了购对。GLSL中的結(jié)構(gòu)體在設(shè)置uniform時(shí)并沒有什么特別之處。結(jié)構(gòu)體只是作為uniform變量的一個(gè)封裝陶因,所以如果想填充這個(gè)結(jié)構(gòu)體的話骡苞,我們?nèi)孕枰獙?duì)每個(gè)單獨(dú)的uniform進(jìn)行設(shè)置,但這次要帶上結(jié)構(gòu)體名的前綴:
lightingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
lightingShader.setFloat("material.shininess", 32.0f);
我們將環(huán)境光和漫反射分量設(shè)置成我們想要讓物體所擁有的顏色坑赡,而將鏡面分量設(shè)置為一個(gè)中等亮度的顏色烙如,我們不希望鏡面分量在這個(gè)物體上過于強(qiáng)烈。我們將反光度保持為32∫惴瘢現(xiàn)在我們能夠程序中非常容易地修改物體的材質(zhì)了亚铁。
運(yùn)行程序,你應(yīng)該會(huì)得到下面這樣的結(jié)果:
光的屬性
這個(gè)物體太亮了螟加。物體過亮的原因是環(huán)境光徘溢、漫反射和鏡面光這三個(gè)顏色對(duì)任何一個(gè)光源都會(huì)去全力反射。光源對(duì)環(huán)境光捆探、漫反射和鏡面光分量也具有著不同的強(qiáng)度然爆。前面的教程,我們通過使用一個(gè)強(qiáng)度值改變環(huán)境光和鏡面光強(qiáng)度的方式解決了這個(gè)問題黍图。我們想做一個(gè)類似的系統(tǒng)曾雕,但是這次是要為每個(gè)光照分量都指定一個(gè)強(qiáng)度向量。如果我們假設(shè)lightColor
是vec3(1.0)
助被,代碼會(huì)看起來像這樣:
vec3 ambient = vec3(1.0) * material.ambient;
vec3 diffuse = vec3(1.0) * (diff * material.diffuse);
vec3 specular = vec3(1.0) * (spec * material.specular);
所以物體的每個(gè)材質(zhì)屬性對(duì)每一個(gè)光照分量都返回了最大的強(qiáng)度剖张。對(duì)單個(gè)光源來說,這些vec3(1.0)值同樣可以分別改變揩环,而這通常就是我們想要的∩ε現(xiàn)在,物體的環(huán)境光分量完全地影響了立方體的顏色丰滑,可是環(huán)境光分量實(shí)際上不應(yīng)該對(duì)最終的顏色有這么大的影響顾犹,所以我們會(huì)將光源的環(huán)境光強(qiáng)度設(shè)置為一個(gè)小一點(diǎn)的值,從而限制環(huán)境光顏色:
vec3 ambient = vec3(0.1) * material.ambient;
我們可以用同樣的方式修改光源的漫反射和鏡面光強(qiáng)度。這和我們?cè)谏弦还?jié)中所做的極為相似炫刷,你可以說我們已經(jīng)創(chuàng)建了一些光照屬性來影響每個(gè)單獨(dú)的光照分量擎宝。我們希望為光照屬性創(chuàng)建一個(gè)與材質(zhì)結(jié)構(gòu)體類似的結(jié)構(gòu)體:
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
一個(gè)光源對(duì)它的ambient、diffuse和specular光照有著不同的強(qiáng)度浑玛。環(huán)境光照通常會(huì)設(shè)置為一個(gè)比較低的強(qiáng)度认臊,因?yàn)槲覀儾幌Mh(huán)境光顏色太過顯眼。光源的漫反射分量通常設(shè)置為光所具有的顏色锄奢,通常是一個(gè)比較明亮的白色失晴。鏡面光分量通常會(huì)保持為vec3(1.0),以最大強(qiáng)度發(fā)光拘央。注意我們也將光源的位置添加到了結(jié)構(gòu)體中涂屁。
和材質(zhì)uniform
一樣,我們需要更新片段著色器:
vec3 ambient = light.ambient * material.ambient;
vec3 diffuse = light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);
我們接下來在程序中設(shè)置光照強(qiáng)度:
lightingShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
lightingShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); // 將光照調(diào)暗了一些以搭配場(chǎng)景
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
現(xiàn)在我們調(diào)整了光照對(duì)物體材質(zhì)的影響灰伟,我們應(yīng)該能得到一個(gè)更類似于上一節(jié)的視覺效果拆又。但這次我們有了對(duì)光照和物體材質(zhì)的完全掌控:
不同的光源顏色
到目前為止,我們都只對(duì)光源設(shè)置了從白到灰到黑范圍內(nèi)的顏色栏账,這樣只會(huì)改變物體各個(gè)分量的強(qiáng)度帖族,而不是它的真正顏色。由于現(xiàn)在能夠非常容易地訪問光照的屬性了挡爵,我們可以隨著時(shí)間改變它們的顏色竖般,從而獲得一些非常有意思的效果。由于所有的東西都在片段著色器中配置好了茶鹃,修改光源的顏色非常簡(jiǎn)單涣雕,我們能夠立刻創(chuàng)造一些很有趣的效果:
你可以看到,不同的光照顏色能夠極大地影響物體的最終顏色輸出闭翩。由于光照顏色能夠直接影響物體能夠反射的顏色(回想顏色這一節(jié))挣郭,這對(duì)視覺輸出有著顯著的影響。
我們可以利用sin
和glfwGetTime
函數(shù)改變光源的環(huán)境光和漫反射顏色疗韵,從而很容易地讓光源的顏色隨著時(shí)間變化:
glm::vec3 lightColor;
lightColor.x = sin(glfwGetTime() * 2.0f);
lightColor.y = sin(glfwGetTime() * 0.7f);
lightColor.z = sin(glfwGetTime() * 1.3f);
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // 降低影響
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影響
lightingShader.setVec3("light.ambient", ambientColor);
lightingShader.setVec3("light.diffuse", diffuseColor);
嘗試并實(shí)驗(yàn)一些光照和材質(zhì)值兑障,看看它們是怎樣影響視覺輸出的。你可以在這里找到程序的源碼蕉汪。
#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 <learnopengl/shader_m.h>
#include <learnopengl/camera.h>
#include <iostream>
void framebuffer_size_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);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
// lighting
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// configure global opengl state
// -----------------------------
glEnable(GL_DEPTH_TEST);
// build and compile our shader zprogram
// ------------------------------------
Shader lightingShader("3.1.materials.vs", "3.1.materials.fs");
Shader lampShader("3.1.lamp.vs", "3.1.lamp.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f
};
// first, configure the cube's VAO (and VBO)
unsigned int VBO, cubeVAO;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(cubeVAO);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube)
unsigned int lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// note that we update the lamp's position attribute's stride to reflect the updated buffer data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// per-frame time logic
// --------------------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// be sure to activate shader when setting uniforms/drawing objects
lightingShader.use();
lightingShader.setVec3("light.position", lightPos);
lightingShader.setVec3("viewPos", camera.Position);
// light properties
glm::vec3 lightColor;
lightColor.x = sin(glfwGetTime() * 2.0f);
lightColor.y = sin(glfwGetTime() * 0.7f);
lightColor.z = sin(glfwGetTime() * 1.3f);
glm::vec3 diffuseColor = lightColor * glm::vec3(0.5f); // decrease the influence
glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // low influence
lightingShader.setVec3("light.ambient", ambientColor);
lightingShader.setVec3("light.diffuse", diffuseColor);
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
// material properties
lightingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f); // specular lighting doesn't have full effect on this object's material
lightingShader.setFloat("material.shininess", 32.0f);
// view/projection transformations
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();
lightingShader.setMat4("projection", projection);
lightingShader.setMat4("view", view);
// world transformation
glm::mat4 model;
lightingShader.setMat4("model", model);
// render the cube
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
// also draw the lamp object
lampShader.use();
lampShader.setMat4("projection", projection);
lampShader.setMat4("view", view);
model = glm::mat4();
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
lampShader.setMat4("model", model);
glBindVertexArray(lightVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &cubeVAO);
glDeleteVertexArrays(1, &lightVAO);
glDeleteBuffers(1, &VBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera.ProcessKeyboard(FORWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos;
lastY = ypos;
camera.ProcessMouseMovement(xoffset, yoffset);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
}
后記
未完流译,待續(xù)~~~