計(jì)算機(jī)圖形學(xué)(OPENGL):光照貼圖

本文同時(shí)發(fā)布在我的個(gè)人博客上:https://dragon_boy.gitee.io

光照貼圖

??在實(shí)際應(yīng)用中,一個(gè)模型包含不同的組件,每個(gè)組件都有不同的材質(zhì)表現(xiàn)。如果用上一節(jié)的內(nèi)容來(lái)實(shí)現(xiàn)這一特點(diǎn)是不夠的,接下來(lái)介紹漫反射貼圖和高光貼圖。

漫反射貼圖

??我們以紋理為基礎(chǔ)來(lái)實(shí)現(xiàn)漫反射貼圖。我們用下面的帶金屬邊緣的箱子圖片來(lái)進(jìn)行學(xué)習(xí):



??為了使用漫反射貼圖,我們同樣定義一個(gè)材質(zhì)結(jié)構(gòu)體,但不同的是,我們將diffuse屬性設(shè)置為sampler2D類型,我們不在需要環(huán)境光屬性(由于簡(jiǎn)化了環(huán)境光的定義,這里使用環(huán)境光屬性對(duì)結(jié)果沒有什么影響,當(dāng)然,我們可以同樣定義環(huán)境光貼圖來(lái)影響結(jié)果):

struct Material
{
  smapler2D diffuse;
  vec3 specular;
  float shininess;
};
...
in vec2 TexCoords;

??這樣我們就可以計(jì)算漫反射的結(jié)果:

vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));

??這里我們將材質(zhì)的環(huán)境光設(shè)置為材質(zhì)漫反射的值:

vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));

??這里提供新增紋理坐標(biāo)的頂點(diǎn)數(shù)組:

float vertices[] = {
    // 位置                 // 法線               //紋理
    -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,  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,  0.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,  1.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,  0.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,  1.0f, 0.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,  1.0f, 1.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, 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,  0.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,  1.0f, 1.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, 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,  0.0f, 1.0f
};

??更新一下 頂點(diǎn)著色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
...
out vec2 TexCoords;

void main()
{
    ...
    TexCoords = aTexCoords;
}  

??同時(shí)記住更新VAO的設(shè)置,并為漫反射貼圖設(shè)置ID,并激活和綁定紋理:

lightingShader.setInt("material.diffuse", 0);
...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);

??運(yùn)行結(jié)果如下:


高光貼圖

??從上面的結(jié)果我們可以發(fā)現(xiàn)一些問題,金屬邊的高光與木紋的高光沒什么區(qū)別,這是不符合實(shí)際的。同樣的,為解決這個(gè)問題,我們?yōu)楦吖獾娘@示設(shè)置高光貼圖(通過(guò)灰度值來(lái)控制高光的強(qiáng)弱)。我們使用下面的圖片來(lái)作為高光貼圖:



??原則上木紋處也有高光,但這里我們暫時(shí)忽略掉。
??接下來(lái)的操作就與漫反射貼圖一樣了。修改結(jié)構(gòu)體:

struct Material {
    sampler2D diffuse;
    sampler2D specular;
    float     shininess;
};  

??修改片元著色器的main函數(shù):

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));
FragColor = vec4(ambient + diffuse + specular, 1.0);   

??設(shè)置貼圖ID,并激活和綁定貼圖:

lightingShader.setInt("material.specular", 1);
...
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);  

??運(yùn)行結(jié)果如下:


??可以看到結(jié)果比較真實(shí)了。這里貼出原文代碼:Code。

??使用漫反射貼圖和高光貼圖我們可以為模型增添許多細(xì)節(jié),當(dāng)然,還有許多諸如法線貼圖,凹凸貼圖,反射貼圖的技術(shù)來(lái)為模型增添更多的細(xì)節(jié),這些將在之后講解。
??最后,請(qǐng)多多關(guān)注原文:https://learnopengl.com/Lighting/Lighting-maps

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容