OpenGL 圖形庫(kù)的使用(十三)—— 光照之材質(zhì)

版本記錄

版本號(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è)lightColorvec3(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)槲覀儾幌Mh(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ì)視覺輸出有著顯著的影響。

我們可以利用singlfwGetTime函數(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ù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肤无,隨后出現(xiàn)的幾起案子先蒋,更是在濱河造成了極大的恐慌骇钦,老刑警劉巖宛渐,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡窥翩,警方通過查閱死者的電腦和手機(jī)业岁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寇蚊,“玉大人笔时,你說我怎么就攤上這事≌贪叮” “怎么了允耿?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)扒怖。 經(jīng)常有香客問我较锡,道長(zhǎng),這世上最難降的妖魔是什么盗痒? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任蚂蕴,我火速辦了婚禮,結(jié)果婚禮上俯邓,老公的妹妹穿的比我還像新娘骡楼。我一直安慰自己,他們只是感情好稽鞭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布鸟整。 她就那樣靜靜地躺著,像睡著了一般朦蕴。 火紅的嫁衣襯著肌膚如雪吃嘿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天梦重,我揣著相機(jī)與錄音兑燥,去河邊找鬼。 笑死琴拧,一個(gè)胖子當(dāng)著我的面吹牛降瞳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚓胸,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼挣饥,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了沛膳?” 一聲冷哼從身側(cè)響起扔枫,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锹安,沒想到半個(gè)月后短荐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倚舀,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年忍宋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痕貌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糠排,死狀恐怖舵稠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情入宦,我是刑警寧澤哺徊,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站乾闰,受9級(jí)特大地震影響唉工,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汹忠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一淋硝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宽菜,春花似錦谣膳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阵幸,卻和暖如春花履,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挚赊。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工诡壁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荠割。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓妹卿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蔑鹦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夺克,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容