從0開(kāi)始的OpenGL學(xué)習(xí)(十一)-基本光照模擬

本章主要解決一個(gè)問(wèn)題:

如何用OpenGL模擬基本光照臊岸?

引言

之前的章節(jié)中,我們?yōu)轫旤c(diǎn)設(shè)置了顏色激况,也將紋理圖貼到了立方體的模型上,算是可以渲染3D場(chǎng)景了膘魄。然而乌逐,僅僅如此并不能讓我們感覺(jué)到有趣。在現(xiàn)實(shí)世界中创葡,我們看到的各種絢爛的場(chǎng)景無(wú)一不是各種光照交織而成的浙踢。所以,為了讓我們的場(chǎng)景更酷更炫灿渴,我們必須要學(xué)習(xí)光照的知識(shí)洛波。我們一定要在計(jì)算機(jī)中也能渲染出那種逼真的酷炫效果。

在本文中骚露,你將能看到:

  • 顏色的原理
  • 環(huán)境光原理
  • 漫反射光原理
  • 鏡面高光原理
  • 顯示一個(gè)包含所有這些光的場(chǎng)景

一蹬挤、顏色

在現(xiàn)實(shí)世界中,每個(gè)物體都有自己的顏色荸百,所有的顏色幾乎可以說(shuō)是無(wú)窮無(wú)盡的闻伶。在計(jì)算機(jī)世界中,我們需要把無(wú)窮無(wú)盡的現(xiàn)實(shí)世界的顏色“映射”到計(jì)算機(jī)世界中有限的顏色上够话。不過(guò)不用擔(dān)心蓝翰,現(xiàn)代計(jì)算機(jī)可以模擬非常多的顏色,多到你根本分辨不出兩種顏色的區(qū)別女嘲。

在OpenGL中畜份,我們用一個(gè)紅色,綠色和藍(lán)色的分量組成一個(gè)RGB格式的向量來(lái)表示顏色欣尼。舉個(gè)例子爆雹,一個(gè)珊瑚紅色的顏色向量是這樣的:

glm::vec3 coral(1.0f, 0.5f, 0.31f);

事實(shí)上停蕉,物體本身并沒(méi)有顏色。我們看到的顏色是物體表面對(duì)光照的反射屬性不同钙态,反射出來(lái)的不同的光的顏色慧起。

顏色

可以看到,物體反射出來(lái)的紅色最多册倒,將其他的顏色掩蓋之后蚓挤,我們看到的就是一個(gè)紅色的物體,未被反射出來(lái)的光都被物體吸收了驻子。

那么如何在OpenGL中模擬這種情況呢灿意?其實(shí)我們已經(jīng)定義好了。在上面定義的coral變量中崇呵,我們指明了紅色會(huì)完全反射(1.0f)缤剧,綠色會(huì)反射一半(0.5f),而藍(lán)色會(huì)反射31%(0.31f)域慷。當(dāng)有一束白色的光(1.0f, 1.0f, 1.0f)光照射到coral上時(shí)荒辕,將兩個(gè)向量相乘,所得到的向量就是最終物體上的顏色向量芒粹。

glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor;  // = (1.0f, 0.5f, 0.31f)

顏色的部分就講到這里兄纺,接下來(lái)我們來(lái)說(shuō)說(shuō)光照。

實(shí)現(xiàn)一個(gè)有光照的場(chǎng)景

在之后的章節(jié)中化漆,我們會(huì)通過(guò)模擬現(xiàn)實(shí)生活中的光照實(shí)現(xiàn)一些非常有趣的效果估脆。所以,撇開(kāi)之前的紋理座云,我們重新來(lái)弄一個(gè)簡(jiǎn)單的場(chǎng)景疙赠,再往里面添加光照效果。

我們首先要做的就是創(chuàng)建一個(gè)可以接收光照的物體朦拖,方便起見(jiàn)圃阳,還是用一個(gè)立方體盒子。我們還需要一個(gè)東西來(lái)模擬光源璧帝,東西越簡(jiǎn)單越好捍岳,最好還是一個(gè)立方體盒子,嘿嘿睬隶。

填充VBO锣夹,設(shè)置頂點(diǎn)屬性等等的工作我們已經(jīng)非常熟悉,在這里就不啰嗦了苏潜。不熟悉的童鞋可以參照之前的例子银萍。

新的立方體上,我們只需要位置屬性恤左,去除掉之前的紋理贴唇,在頂點(diǎn)著色器中對(duì)頂點(diǎn)進(jìn)行轉(zhuǎn)換就可以了搀绣。精簡(jiǎn)之后的頂點(diǎn)著色器如下:

//頂點(diǎn)著色器代碼
#version 330 core

layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

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

確保你已經(jīng)更新了頂點(diǎn)屬性的配置。只有位置屬性的頂點(diǎn)跨度為3*sizeof(float)戳气。

//链患!頂點(diǎn)屬性環(huán)境
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

//頂點(diǎn)屬性設(shè)置
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

這些代碼應(yīng)該是非常直觀易懂的。定義完立方體之后物咳,我們?cè)賮?lái)弄一個(gè)片元著色器锣险。

#version 330 core
out vec4 FragColor;
  
uniform vec3 objectColor;
uniform vec3 lightColor;

void main()
{
    FragColor = vec4(lightColor * objectColor, 1.0);
}

片元著色器需要物體顏色和光照顏色兩個(gè)uniform變量來(lái)計(jì)算蹄皱。這里我們根據(jù)之前的理解览闰,直接將兩個(gè)變量相乘,再添加一個(gè)齊次分量后賦值給片元顏色巷折。我們來(lái)設(shè)置物體顏色和光照顏色压鉴。

lightingShader.use();
lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
lightingShader.setVec3("lightColor",  1.0f, 1.0f, 1.0f);

當(dāng)我們改變著色器的時(shí)候,我們只希望物體的顏色變化锻拘,而希望連光源的顏色都變了油吭,所以,這里我們還要多定義一個(gè)片元著色器用于對(duì)光源進(jìn)行渲染署拟。

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0);
}

很簡(jiǎn)單婉宰,只需要將光源設(shè)置成白色就行。當(dāng)我們繪制盒子立方體時(shí)推穷,我們使用前面的那個(gè)著色器心包,當(dāng)我們繪制光源立方體時(shí),我們使用這個(gè)著色器馒铃。

定義一個(gè)光源的位置蟹腾,然后將光源立方體移動(dòng)到指定位置。

glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
...
model = glm::mat4();
model = glm::translate(model, lightPos);
model = glm::scale(model, glm::vec3(0.2f)); 

在渲染的時(shí)候区宇,對(duì)盒子立方體娃殖,要用lightShader,對(duì)光源立方體议谷,要用lampShader炉爆。所有的這些都弄完之后,運(yùn)行出來(lái)的效果應(yīng)該是這樣的:

渲染結(jié)果

如果有問(wèn)題卧晓,參考這里的源碼芬首。

二、基礎(chǔ)光照

現(xiàn)實(shí)世界中的光照受太多因素的影響禀崖,以至于我們根本就沒(méi)有足夠的計(jì)算力來(lái)計(jì)算其所有的因素衩辟。OpenGL中使用一些簡(jiǎn)單的模型來(lái)模擬真實(shí)世界中的光照,將這些模型組合起來(lái)后波附,我們也能得到非常逼真的效果艺晴。有一種模型叫做:馮氏光照模型(Phong light model)昼钻。這種模型有三種光照組成:環(huán)境光(ambient),漫反射光(diffuse)和鏡面高光(specular)封寞。Phong光照模型是圖形學(xué)中最常用的模型然评,用好之后效果也非常贊。來(lái)看一組效果圖:

馮氏光照模型
  • 環(huán)境光(Ambient):即便是在漆黑的夜晚也還是有少許亮光的存在(月亮狈究,遠(yuǎn)處的燈光碗淌,星光),所以抖锥,物體不會(huì)是完全的黑色亿眠。為了模擬這種情況,我們通常會(huì)給定一個(gè)常量顏色值充當(dāng)環(huán)境光磅废。
  • 漫反射光(diffuse):模擬光直接照射到物體上的情況纳像。這是光照模型中最具有特點(diǎn)的組成部分。越朝向光源的部分看起來(lái)就越亮拯勉。
  • 鏡面高光(specular):模擬一個(gè)非常光滑的物體上的聚光燈效果竟趾。鏡面高光受光照顏色的影響比受物體顏色的影響更大。

想要讓場(chǎng)景中的效果逼真宫峦,我們至少需要模擬這三種光照岔帽。先從最簡(jiǎn)單的開(kāi)始:環(huán)境光(Ambient)

環(huán)境光(Ambient)

光照通常不會(huì)來(lái)自一個(gè)單一的光源,而是在場(chǎng)景中各個(gè)光源导绷,各種反射或折射綜合而成的一個(gè)效果犀勒。將這些因素都考慮進(jìn)去的算法稱作全局光照算法,但是這些算法非常難懂而且運(yùn)行起來(lái)代價(jià)高昂诵次。

于是账蓉,我們自然而然地尋找一些簡(jiǎn)單的方法來(lái)這些高昂的算法,終于逾一,我們找到了環(huán)境光這種模型铸本。就如之前所說(shuō),我們使用一個(gè)小常量顏色來(lái)代替照射到物體的環(huán)境光遵堵。

使用環(huán)境光非常的簡(jiǎn)單箱玷,我們只需要設(shè)置一個(gè)環(huán)境光強(qiáng)度,用這個(gè)強(qiáng)度值乘上光源的顏色得到環(huán)境光顏色陌宿。最后锡足,用環(huán)境光顏色乘上物體的顏色,得到物體在光照下的最終顏色值壳坪。使用了環(huán)境光的代碼如下:

void main()
{
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

    vec3 result = ambient * objectColor;
    FragColor = vec4(result, 1.0f);
}

附上運(yùn)行的效果圖:


環(huán)境光效果

漫反射光(Diffuse)

相對(duì)于環(huán)境光(ambient)來(lái)說(shuō)舶得,漫反射光(Diffuse)在物體上的表現(xiàn)更明顯,也給了物體最直觀的特征爽蝴。為了能更好的理解漫反射沐批,請(qǐng)看下面的一張圖:

漫反射

我們的物體表面并不會(huì)那么光滑平整纫骑,光線照射到物體表面的時(shí)候會(huì)產(chǎn)生方向不同的反射效果,這些反射就是漫反射九孩。漫反射光(Diffuse)期望模擬的先馆,就是這種光線照射上來(lái)之后,經(jīng)過(guò)物體復(fù)雜的漫反射之后所呈現(xiàn)出的整體的光照效果躺彬。

那么煤墙,我們?nèi)绾斡?jì)算漫反射呢?

  • 法向量(Normal Vector):垂直于頂點(diǎn)表面的一個(gè)向量
  • 光線向量:片元位置和光源之間的一個(gè)方向向量宪拥,用于計(jì)算與法向量之間的夾角仿野。
  • 計(jì)算光線向量和法向量之間的夾角,如果夾角<90度江解,說(shuō)明物體是對(duì)著光源的设预,再根據(jù)cos值來(lái)計(jì)算強(qiáng)度。如果夾角>90度犁河,說(shuō)明物體背對(duì)光源,光照也就沒(méi)效果了魄梯。
法向量(Normal Vector)

法向量是垂直于頂點(diǎn)表面的單位向量桨螺。因?yàn)轫旤c(diǎn)本身是沒(méi)有表面這個(gè)概念的,所以我們會(huì)參考其周?chē)捻旤c(diǎn)來(lái)確定它的表面酿秸,從而計(jì)算出法向量灭翔。在計(jì)算法向量的時(shí)候,我們用了一些小技巧(叉乘)辣苏。因?yàn)?D立方體并不復(fù)雜肝箱,所以我們手動(dòng)計(jì)算了所有頂點(diǎn)的法向量。完整的頂點(diǎn)結(jié)構(gòu)如下:

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
};

當(dāng)我們加入了額外的頂點(diǎn)屬性之后稀蟋,條件反射式的就要去修改傳遞給OpenGL的信息煌张。請(qǐng)注意,兩個(gè)立方體雖然共用一組數(shù)據(jù)退客,但是物體需要法線信息骏融,而光源不需要法線信息。因此萌狂,一個(gè)重要的操作就是把渲染物體的VAO和渲染光源的VAO分開(kāi)档玻,各自設(shè)置自己的頂點(diǎn)屬性:物體需要全部的頂點(diǎn)屬性,光源只需要位置的屬性茫藏。

// VBO误趴,物體VAO
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);

// 位置屬性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 法向量屬性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);


// 光源VAO (VBO相同,因?yàn)轫旤c(diǎn)數(shù)據(jù)是同一組)
unsigned int lightVAO;
glGenVertexArrays(1, &lightVAO);
glBindVertexArray(lightVAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
// 位置屬性(只需要更新跨度就可以了)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

接著光照頂點(diǎn)著色器中要接收法向量進(jìn)行操作务傲,然后輸出法向量凉当,片元著色器中也要接收法向量進(jìn)行計(jì)算碧囊。

//頂點(diǎn)著色器
...
layout (location = 1) in vec3 aNormal;
...
out vec3 Normal;
...
void main()
{
    gl_Position = projection * view * model * vec4 (aPos, 1.0f);
    Normal = aNormal;
}
//片元著色器
...
in vec3 Normal;
...
計(jì)算漫反射顏色

現(xiàn)在我們的頂點(diǎn)有了法向量,還缺光源位置和片元位置纤怒。光源位置是一個(gè)靜態(tài)的變量我們直接在片元著色器中定義成uniform變量糯而。

//片元著色器
uniform vec3 lightPos;

而后流码,在主函數(shù)中設(shè)置光源位置芍殖。

lightingShader.setVec3("lightPos", lightPos);

最后,我們還要計(jì)算出片元的位置劝赔。要計(jì)算片元位置烘豹,我們只要將位置與模型矩陣相乘就可以了瓜贾。

out vec3 FragPos;
out vec3 Normal;

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

對(duì)了,別忘了在片元著色器中加上接受片元位置的變量携悯。in vec3 FragPos;

緊接著祭芦,我們來(lái)計(jì)算漫反射顏色。思路是:

  • 計(jì)算片元指向光源的向量(光源向量)
  • 規(guī)范化光源向量和法線向量憔鬼。
  • 計(jì)算光源向量和法線向量的點(diǎn)積龟劲,將該值乘上光源顏色值
//計(jì)算光源向量,規(guī)范化兩個(gè)向量
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);  
//計(jì)算點(diǎn)積轴或,修正點(diǎn)積值昌跌,乘上光源顏色值
float diff = max(dot(norm, lightDir), 0.0);  //負(fù)數(shù)沒(méi)有意義
vec3 diffuse = diff * lightColor;

最后的最后,將環(huán)境光(ambient)和漫反射(diffuse)相加起來(lái)照雁,再乘上物體顏色蚕愤,得到最終的結(jié)果。

運(yùn)行效果

如果你運(yùn)行的效果和上圖不同饺蚊,可以參考這里的源碼萍诱。

還有一件事

前面的代碼中,我們直接將法向量從頂點(diǎn)著色器傳遞到了片元著色器污呼。不過(guò)裕坊,我們?cè)谟?jì)算的時(shí)候,用的都是世界空間中的坐標(biāo)曙求,難道我們不該把法向量也轉(zhuǎn)換成世界空間中的坐標(biāo)嗎碍庵?原則上,是的悟狱,不過(guò)轉(zhuǎn)換操作并不是乘上一個(gè)模型矩陣那么簡(jiǎn)單静浴。

首先,法向量只有方向有意義(因?yàn)槲覀儾恍枰诳臻g中的位置信息)挤渐。所以苹享,我們只對(duì)法向量的比例變換和旋轉(zhuǎn)變換感興趣。要去除模型矩陣中的平移操作的話,需要將法向量的齊次坐標(biāo)(w)設(shè)置為0.

然后得问,如果模型矩陣進(jìn)行了一個(gè)不規(guī)則的比例變換囤攀,那么即使法向量乘上模型矩陣,法向量也不會(huì)和表面垂直了宫纬,如下圖所示:

不規(guī)則比例變換

法向量不和表面垂直會(huì)嚴(yán)重扭曲光照效果焚挠。

解決這個(gè)問(wèn)題的方法是為法向量量身定制一個(gè)模型矩陣。這個(gè)矩陣被稱為向量矩陣(normal matrix)漓骚,其使用了一些線性代數(shù)的操作來(lái)消除對(duì)法向量的比例變換影響蝌衔。

詳細(xì)的原理超出了本文的討論范圍,具體內(nèi)容有興趣的童鞋可以去網(wǎng)上找蝌蹂。下面直接給出計(jì)算的方法:

Normal = mat3(transpose(inverse(model)) * aNormal;

模型矩陣的逆矩陣的轉(zhuǎn)置矩陣噩斟,就是這貨。

前面我們沒(méi)對(duì)法向量轉(zhuǎn)換卻沒(méi)出問(wèn)題純粹是僥幸孤个,因?yàn)槲覀儧](méi)有對(duì)模型進(jìn)行任何比例變換或者是旋轉(zhuǎn)的操作剃允。但是,一旦有這兩種操作齐鲤,就必須對(duì)法向量進(jìn)行變換斥废。

鏡面高光(Specular)

挺住,我們還剩最有一個(gè)光照內(nèi)容了佳遂!

和漫反射很類似营袜,鏡面高光液是基于光源方向向量和物體表面法向量的。不同的是丑罪,鏡面高光也取決于觀察者看物體的角度。想象一下如果物體像鏡子一樣光滑凤壁,我們就能在某個(gè)位置看到非常強(qiáng)烈的光照吩屹。原理如下圖所示:

鏡面高光

將光源方向沿著法向量對(duì)稱一下,我們就得到了反射光向量拧抖。然后煤搜,計(jì)算出反射光向量和觀察者方向的角度差,角度差越小唧席,光照越強(qiáng)擦盾。

觀察者方向是一個(gè)額外我們需要計(jì)算的東西,可以通過(guò)觀察者位置(世界空間)和片元位置計(jì)算出來(lái)淌哟。然后迹卢,計(jì)算出鏡面反射強(qiáng)度,乘以光照顏色徒仓,將它與環(huán)境光和漫反射光加起來(lái)腐碱,得到的就是完整的光照效果。

在片元著色器中添加觀察者位置變量掉弛,然后在主循環(huán)中設(shè)置症见。

uniform vec3 viewPos;
lightingShader.setVec3("viewPos", camera.Position);

設(shè)置一個(gè)鏡面反射強(qiáng)度喂走,控制鏡面反射光對(duì)物體的影響程度。

float specularStrength = 0.5;

計(jì)算反射光向量谋作。

vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);

最后芋肠,計(jì)算鏡面高光的強(qiáng)度,用下面的公式:

float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;

我們先計(jì)算了觀察方向和反射方向的夾角(并確保其大于0)遵蚜,然后計(jì)算了它的32次方值帖池。這個(gè)32表示了高光的光澤度信息。光澤度越高谬晕,高光范圍越集中碘裕。如下圖所示:

不同光澤度的區(qū)別

通常,光澤度設(shè)置成32就可以了攒钳。最后帮孔,把鏡面高光的部分添加到總的結(jié)果里面去。我們就完成了馮氏光照模型不撑。

馮氏光照模型

完整的代碼在這里文兢。

現(xiàn)在,你應(yīng)該領(lǐng)教了著色器的強(qiáng)大之處了吧焕檬。只需要少量的信息姆坚,著色器就能計(jì)算出光照效果。之后我們會(huì)把光照效果挖掘地更深实愚!

總結(jié)

在這篇文章里兼呵,我們學(xué)習(xí)了顏色的原理,學(xué)習(xí)了如何用環(huán)境光腊敲,漫反射光击喂,鏡面高光來(lái)模擬現(xiàn)實(shí)中復(fù)雜的光照。同時(shí)碰辅,我們也實(shí)踐了學(xué)到的知識(shí)懂昂,渲染了一個(gè)使用馮氏光照模型的場(chǎng)景。收拾收拾腦中的知識(shí)没宾,將這些知識(shí)都聯(lián)系起來(lái)凌彬。

下一篇
目錄
上一篇

參考資料:
www.learningopengl.com(非常好的網(wǎng)站,建議學(xué)習(xí))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末循衰,一起剝皮案震驚了整個(gè)濱河市铲敛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羹蚣,老刑警劉巖原探,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咽弦,居然都是意外死亡徒蟆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)型型,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)段审,“玉大人,你說(shuō)我怎么就攤上這事闹蒜∷峦鳎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵绷落,是天一觀的道長(zhǎng)姥闪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)砌烁,這世上最難降的妖魔是什么筐喳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮函喉,結(jié)果婚禮上避归,老公的妹妹穿的比我還像新娘。我一直安慰自己管呵,他們只是感情好梳毙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著捐下,像睡著了一般账锹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坷襟,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天牌废,我揣著相機(jī)與錄音,去河邊找鬼啤握。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晶框,可吹牛的內(nèi)容都是我干的排抬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼授段,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蹲蒲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起侵贵,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤届搁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體卡睦,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宴胧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了表锻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恕齐。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瞬逊,靈堂內(nèi)的尸體忽然破棺而出显歧,到底是詐尸還是另有隱情,我是刑警寧澤确镊,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布士骤,位于F島的核電站,受9級(jí)特大地震影響蕾域,放射性物質(zhì)發(fā)生泄漏拷肌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一束铭、第九天 我趴在偏房一處隱蔽的房頂上張望廓块。 院中可真熱鬧,春花似錦契沫、人聲如沸带猴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拴清。三九已至,卻和暖如春会通,著一層夾襖步出監(jiān)牢的瞬間口予,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工涕侈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沪停,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓裳涛,卻偏偏與公主長(zhǎng)得像木张,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子端三,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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

  • 版本記錄 前言 OpenGL 圖形庫(kù)項(xiàng)目中一直也沒(méi)用過(guò)舷礼,最近也想學(xué)著使用這個(gè)圖形庫(kù),感覺(jué)還是很有意思郊闯,也就自然想著...
    刀客傳奇閱讀 6,026評(píng)論 0 2
  • 現(xiàn)實(shí)世界的光照是極其復(fù)雜的妻献,而且會(huì)受到諸多因素的影響蛛株,這是以目前我們所擁有的處理能力無(wú)法模擬的。因此OpenGL的...
    IceMJ閱讀 1,948評(píng)論 1 6
  • 版本記錄 前言 OpenGL ES圖形庫(kù)項(xiàng)目中一直也沒(méi)用過(guò)育拨,最近也想學(xué)著使用這個(gè)圖形庫(kù)谨履,感覺(jué)還是很有意思,也就自然...
    刀客傳奇閱讀 2,919評(píng)論 0 2
  • 寫(xiě)于莫名其妙的一個(gè)晚上至朗。 我躺著在床上屉符,風(fēng)扇呼呼響,過(guò)往的車(chē)輛偶爾呼嘯锹引,騎車(chē)的年輕的男孩子路過(guò)大聲喧嘩矗钟,夏天的夜晚...
    Nemure閱讀 277評(píng)論 0 1
  • 忘記背后,努力面前嫌变,事情是一點(diǎn)點(diǎn)做出來(lái)的( ? ?ω?? )
    猴砸0閱讀 161評(píng)論 0 0