OpenGL學習筆記13 Materials

2021-10-08 14:56:47 字數 4456 閱讀 4038

在現實世界中,每個物體對光有不同的反應。例如,鋼製物品通常比陶土花瓶更閃亮,而木製容器對光線的反應與鋼製容器不同。一些物體反射光沒有太多散射導致小高光和其他散射很多給高光乙個更大的半徑。如果我們想要在opengl中模擬幾種型別的物件,我們必須定義特定於每個表面的材質屬性。

在前一章中,我們定義了乙個物體和光的顏色來定義物體的視覺輸出,並結合了環境光和鏡面光的強度。當描述乙個表面時,我們可以為三個照明元件分別定義乙個材質顏色:環境光,漫射光和高光。通過為每個元件指定顏色,我們可以對表面的顏色輸出進行細粒度控制。現在給這三種顏色新增乙個光澤元件,我們就有了我們需要的所有材質屬性:

#version 330 core

struct material ;

uniform material material;

在fragment shader中,我們建立了乙個struct來儲存表面的材質屬性。我們也可以將它們儲存為單獨的uniform值,但是將它們儲存為結構可以使其更有組織。我們首先定義結構的布局,然後簡單地宣告乙個uniform變數,將新建立的結構作為其型別。

正如你所看到的,我們為phong照明的每個元件定義了乙個顏色向量。環境材質向量定義了在環境光照下表面反射的顏色;這通常與表面的顏色相同。漫反射材質向量定義漫反射光線下表面的顏色。漫反射顏色(就像環境光一樣)設定為所需表面的顏色。高光材質向量設定表面高光的顏色(或者甚至可能反射特定於表面的顏色)。最後,亮度影響鏡面高光的散射/半徑。

通過這4個元件定義乙個物件的材質,我們可以模擬許多真實世界的材質。在devernay.free.frdevernay.free.fr 上有乙個表,顯示了模擬真實材料的材料屬性列表。下面的展示了幾個真實世界的材質值對我們的立方體的影響:

正如你所看到的,通過正確地指定乙個表面的材料屬性,它似乎改變了我們對這個物體的感知。效果很明顯,但是為了得到更真實的結果,我們需要用更複雜的東西來替換立方體。在模型載入model loading章節中,我們將討論更複雜的形狀。

為乙個物體弄清楚正確的材質設定是乙個困難的壯舉,大部分需要實驗和大量的經驗。由於材料錯位而完全破壞物品的視覺效果,這種情況並不少見。

讓我們嘗試在著色器中實現這樣乙個材質系統。

我們在fragment shader中建立了乙個uniform的材質結構,所以接下來我們要根據新的材質屬性改變光照計算。由於所有的材質變數都儲存在乙個結構體中,我們可以從material uniform中訪問它們:

void main()

正如你所看到的,我們現在可以在任何需要的地方訪問材質結構的所有屬性,這次利用材質的顏色計算輸出的結果顏色。每個物體的材質屬性都與它們各自的照明元件相乘。

我們可以在應用程式中通過設定合適的uniform來設定物件的材質。然而,在設定uniform時,glsl中的struct在任何方面都不特殊;結構實際上只充當統一變數的命名空間。如果我們想填充結構,我們將不得不設定單獨的uniform,但字首結構的名稱:

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

我們將環境和漫反射元件設定為我們想要的顏色,將鏡面元件設定為中亮的顏色;我們不希望高光元件太強。我們還將亮度保持在32。

我們現在可以很容易地從應用程式中影響物件的材質。執行程式會得到如下結果:

看起來不太對吧?

這個物體太亮了。物體太亮的原因是環境色、漫射色和高光色從任何光源都被充分反射。光源的環境光、漫射光和鏡面光的強度也各不相同。在前一章中,我們通過改變環境強度和鏡面強度值來解決這個問題。我們想做一些類似的事情,但是這一次通過指定每個照明元件的強度向量。如果我們將lightcolor視覺化為vec3(1.0),**將是這樣的:

vec3 ambient  = vec3(1.0) * material.ambient;

vec3 diffuse = vec3(1.0) * (diff * material.diffuse);

vec3 specular = vec3(1.0) * (spec * material.specular);

因此,物體的每個材質屬性都以光的每個元件的全強度返回。這些vec3(1.0)值可以被每個光源單獨影響,這通常是我們想要的。現在物體的環境元素完全影響了立方體的顏色。環境元素對最終的顏色不會有太大的影響,所以我們可以通過設定較低的環境強度來限制環境色:

vec3 ambient = vec3(0.1) * material.ambient;
我們可以以同樣的方式影響光源的漫射和鏡面強度。這與我們在前一章所做的非常相似;可以說我們已經建立了一些光屬性來分別影響每個照明元件。我們想為燈光屬性建立一些類似於材質結構的東西:

struct light ;

uniform light light;

乙個光源對於它的環境、漫射和鏡面元件有不同的強度。環境光通常設定為低強度,因為我們不希望環境色太佔主導地位。光源的漫反射部分通常設定為我們想要的顏色;通常是明亮的白色。鏡面元件通常保持在全強度的vec3(1.0)發光。注意,我們還在結構體中新增了光的位置向量。

就像材質uniform一樣,我們需要更新fragment shader:

vec3 ambient  = light.ambient * material.ambient;

vec3 diffuse = light.diffuse * (diff * material.diffuse);

vec3 specular = light.specular * (spec * material.specular);

然後我們想在應用程式中設定光線強度:

lightingshader.setvec3("light.ambient",  0.2f, 0.2f, 0.2f);

lightingshader.setvec3("light.diffuse", 0.5f, 0.5f, 0.5f); // darken diffuse light a bit

lightingshader.setvec3("light.specular", 1.0f, 1.0f, 1.0f);

現在我們調整了光線如何影響物體的材質,我們得到了乙個視覺輸出,看起來很像前一章的輸出。但是這一次我們完全控制了燈光和物體的材質:

現在改變物體的視覺方面是相對容易的。讓我們把事情變得有趣一點吧!

到目前為止,我們使用的是淺色,通過選擇從白色到灰色到黑色的顏色來改變單個元件的強度,不影響物體的實際顏色(只影響它的強度)。因為我們現在可以很容易地獲得光的屬性,我們可以隨著時間的推移改變它們的顏色來獲得一些真正有趣的效果。因為所有的東西都已經在fragment shader中設定好了,所以改變光線的顏色是很容易的,並且可以立即建立一些時髦的效果:

正如你所看到的,不同的光色會極大地影響物體的顏色輸出。因為光的顏色直接影響到物體反射的顏色(你可能還記得顏色那一章),它對視覺輸出有很大的影響。

通過sin和glfwgettime,我們可以很容易地隨時間改變光的顏色,通過改變光的環境色和漫反射色:

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

嘗試和實驗幾種照明和材質值,看看它們如何影響視覺輸出。您可以在這裡here. 找到應用程式的源**。

OpenGL學習筆記

我是一名ios開發者,opengl是乙個比較重要的技術。所以就此開啟我的菜鳥之路。opengl open graphics library 是乙個跨程式設計語 言 跨平台的程式設計圖形程式接 它將計算機的資源抽象稱為乙個個opengl的物件,對這些資源的操作抽象為乙個的opengl指令.direct...

OpenGL學習筆記

數學基礎 叉積mv矩陣 文章內容主要來自 計算機圖形學程式設計 使用opengl和c 光柵化過程確定了用以顯示3個頂點所確定的三角形的所有畫素需要繪製的位置 光柵化過程開始時先對三角形的每對頂點進行插值 如果光柵化過程到此為止,那麼呈現出的影象將會是線框模型 使用 glpolygonmode gl ...

OpenGL學習筆記

因工作需要,這些天要研究opengl。我給自己定的目標是 1.節前能熟悉opengl基礎知識 2.確定一款以opengl為基礎的gui 3.學習如何使用該gui的控制項繪製3d選單 今天找到幾個 嵌入式系統使用的是opengl es,是桌面opengl的乙個子集,定義了一系列靈活高效的圖形加速介面。...