国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

內(nèi)蒙古企業(yè)網(wǎng)站制作南寧網(wǎng)絡(luò)推廣服務(wù)商

內(nèi)蒙古企業(yè)網(wǎng)站制作,南寧網(wǎng)絡(luò)推廣服務(wù)商,wordpress注冊(cè)登錄界面,個(gè)人如何辦網(wǎng)站ok終于來(lái)到了立方體貼圖了,在這里面我們可以加入好看的天空包圍盒,這樣的畫我們的背景就不再是黑色的了! 首先,立方體貼圖和前面的sampler2D貼圖一樣,不過(guò)是6個(gè)2D組成的立方體而已。 那么為什么要把6個(gè)組合在一起呢&…

ok終于來(lái)到了立方體貼圖了,在這里面我們可以加入好看的天空包圍盒,這樣的畫我們的背景就不再是黑色的了!

首先,立方體貼圖和前面的sampler2D貼圖一樣,不過(guò)是6個(gè)2D組成的立方體而已。

那么為什么要把6個(gè)組合在一起呢?立方體貼圖可以通過(guò)一個(gè)方向向量來(lái)進(jìn)行索引(或者說(shuō)采樣)。什么意思?

我們類比一下,之前在一個(gè)2D面上我們通過(guò)uv紋理坐標(biāo)來(lái)找到對(duì)應(yīng)的紋理值對(duì)吧。這里也一樣,不過(guò)是通過(guò)一個(gè)方向向量來(lái)獲得。

?假設(shè)我們有一個(gè)立方體、然后又有一個(gè)立方體貼圖,只要立方體中心在原點(diǎn),我就可以通過(guò)立方體表面的位置來(lái)確定對(duì)應(yīng)的方向向量從而確定對(duì)應(yīng)的立方體紋理坐標(biāo)。

創(chuàng)建立方體貼圖

和前面創(chuàng)建貼圖一樣。

unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

不過(guò)因?yàn)橛?個(gè)面,所以需要貼6次。

int width, height, nrChannels;
unsigned char *data;  
for(unsigned int i = 0; i < textures_faces.size(); i++)
{data = stbi_load(textures_faces[i].c_str(), &width, &height, &nrChannels, 0);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}

這里我們有一個(gè)叫做textures_faces的vector,它包含了立方體貼圖所需的所有紋理路徑,并以表中的順序排列。這將為當(dāng)前綁定的立方體貼圖中的每個(gè)面生成一個(gè)紋理。

然后還需要設(shè)置環(huán)繞和過(guò)濾方式

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

可以看到這里出現(xiàn)了個(gè)R坐標(biāo),其實(shí)就是紋理的第三個(gè)維度,和位置的z一樣。

最后在片段著色器中要使用一個(gè)samplerCube就行

天空盒

我們現(xiàn)在下載一個(gè)天空盒到我們的項(xiàng)目中。

?加載天空盒

和之前把圖片加載到gpu一樣,現(xiàn)在是加載一個(gè)cubemap。

unsigned int LoadCubeMapToGPU(std::vector<std::string> faces) {unsigned int textureID;glGenTextures(1, &textureID);glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);int width, height, nrChannels;for (unsigned int i = 0; i < faces.size(); i++) {unsigned char* data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);if (data) {glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);stbi_image_free(data);}else {std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;stbi_image_free(data);}}glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);return textureID;};

然后需要存一個(gè)skybox的圖片vector

float skyboxVertices[] = {// positions          -1.0f,  1.0f, -1.0f,-1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,1.0f,  1.0f, -1.0f,-1.0f,  1.0f, -1.0f,-1.0f, -1.0f,  1.0f,-1.0f, -1.0f, -1.0f,-1.0f,  1.0f, -1.0f,-1.0f,  1.0f, -1.0f,-1.0f,  1.0f,  1.0f,-1.0f, -1.0f,  1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f,  1.0f,1.0f,  1.0f,  1.0f,1.0f,  1.0f,  1.0f,1.0f,  1.0f, -1.0f,1.0f, -1.0f, -1.0f,-1.0f, -1.0f,  1.0f,-1.0f,  1.0f,  1.0f,1.0f,  1.0f,  1.0f,1.0f,  1.0f,  1.0f,1.0f, -1.0f,  1.0f,-1.0f, -1.0f,  1.0f,-1.0f,  1.0f, -1.0f,1.0f,  1.0f, -1.0f,1.0f,  1.0f,  1.0f,1.0f,  1.0f,  1.0f,-1.0f,  1.0f,  1.0f,-1.0f,  1.0f, -1.0f,-1.0f, -1.0f, -1.0f,-1.0f, -1.0f,  1.0f,1.0f, -1.0f, -1.0f,1.0f, -1.0f, -1.0f,-1.0f, -1.0f,  1.0f,1.0f, -1.0f,  1.0f
};std::vector<std::string> faces
{"right.jpg","left.jpg","top.jpg","bottom.jpg","front.jpg","back.jpg"
};

然后需要給這cube給一個(gè)VAO VBO

	unsigned int cubemapTexture = LoadCubeMapToGPU(faces);unsigned int skyboxVAO, skyboxVBO;glGenBuffers(1, &skyboxVBO);glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);glGenVertexArrays(1, &skyboxVAO);glBindVertexArray(skyboxVAO);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

最后寫一個(gè)skybox的shader就好。

#version 330 corelayout(location = 0) in vec3 aPos;out vec3 TexCoords;uniform mat4 projMat;
uniform mat4 viewMat;void main(){gl_Position = projMat*viewMat*vec4(aPos,1.0f);TexCoords = aPos;
}#version 330 core
out vec4 FragColor;
in vec3 TexCoords;uniform samplerCube skybox;void main(){FragColor =	 texture(skybox,TexCoords);
}

可以看到在頂點(diǎn)著色器里面我們把坐標(biāo)信息作為紋理信息傳給了片段著色器,這是因?yàn)閏ubemap的紋理坐標(biāo)就是一個(gè)向量,所以我們直接把原點(diǎn)在世界中心的立方體的各點(diǎn)坐標(biāo)當(dāng)作紋理向量給片段著色器就好。

最后是loop中,我們要記住,畫天空盒,我們得先畫,而且畫的時(shí)候需要把深度測(cè)試關(guān)了,這樣的畫,之后的物體就是畫在背景之前了。

loop中這么寫。

//第一階段
...
//clear screen
...
//skybox
glDepthMask(GL_FALSE);
skyboxShader->use();iewMat = camera.GetViewMatrix();
projMat = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(skyboxShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
glUniformMatrix4fv(glGetUniformLocation(skyboxShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));glBindVertexArray(skyboxVAO);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthMask(GL_TRUE);
...
//木塊 機(jī)器人 其他

不過(guò)結(jié)果不對(duì),我們希望天空盒是以玩家為中心的,這樣不論玩家移動(dòng)了多遠(yuǎn),天空盒都不會(huì)變近,讓玩家產(chǎn)生周圍環(huán)境非常大的印象。然而,當(dāng)前的觀察矩陣會(huì)旋轉(zhuǎn)、縮放和位移來(lái)變換天空盒的所有位置,所以當(dāng)玩家移動(dòng)的時(shí)候,立方體貼圖也會(huì)移動(dòng)!我們希望移除觀察矩陣中的位移部分,讓移動(dòng)不會(huì)影響天空盒的位置向量。

在基礎(chǔ)光照小節(jié)中,我們通過(guò)取4x4矩陣左上角的3x3矩陣來(lái)移除變換矩陣的位移部分。我們可以將觀察矩陣轉(zhuǎn)換為3x3矩陣(移除位移),再將其轉(zhuǎn)換回4x4矩陣,來(lái)達(dá)到類似的效果。

修改viewMat

glm::mat4 view = glm::mat4(glm::mat3(camera.GetViewMatrix()));

優(yōu)化

?在剛剛的過(guò)程中,是先畫天空盒,在這中間關(guān)閉了深度測(cè)試。是因?yàn)槲覀兿胱屍渌矬w畫在天空盒上。不過(guò)這樣不過(guò)高效,是因?yàn)樵诋嬏炜蘸械臅r(shí)候會(huì)對(duì)每個(gè)像素都跑一次片段著色器。

所以我們要最后渲染天空盒。但是怎么做呢?提前深度測(cè)試可以做到,我們先渲染其他東西,然后再提前深度測(cè)試通過(guò)的地方渲染天空盒就行了。

不過(guò)要知道的我們的天空盒只有1x1x1,其他東西很容易就在天空盒上,所以我們需要欺騙深度緩沖,或者說(shuō)讓他認(rèn)為天空盒的深度值有最大,要讓天空盒最深。

在坐標(biāo)系統(tǒng)小節(jié)中我們說(shuō)過(guò),透視除法是在頂點(diǎn)著色器運(yùn)行之后執(zhí)行的,將gl_Position的xyz坐標(biāo)除以w分量。我們又從深度測(cè)試小節(jié)中知道,相除結(jié)果的z分量等于頂點(diǎn)的深度值。使用這些信息,我們可以將輸出位置的z分量等于它的w分量,讓z分量永遠(yuǎn)等于1.0,這樣子的話,當(dāng)透視除法執(zhí)行之后,z分量會(huì)變?yōu)?code>w / w = 1.0。

修改頂點(diǎn)著色器

void main(){vec4 pos = projMat*viewMat*vec4(aPos,1.0);gl_Position = pos.xyww;TexCoords = aPos;
}

修改main中的順序,把天空盒放在其他物體之后,但是是再透明物體之前。

我們還要改變一下深度函數(shù),將它從默認(rèn)的GL_LESS改為GL_LEQUAL。

深度緩沖將會(huì)填充上天空盒的1.0值,所以我們需要保證天空盒在值小于或等于深度緩沖而不是小于時(shí)通過(guò)深度測(cè)試。

結(jié)果和之前一樣

環(huán)境映射

現(xiàn)在我們可以通過(guò)這個(gè)環(huán)境紋理來(lái)給物體一些反射折射的屬性了

反射

?這里灰色向量是我們的觀察方向向量、紅色是法向方向,綠色是反射方向,可以通過(guò)reflect()來(lái)獲得,之后把這個(gè)綠色的向量作為天空盒的紋理方向坐標(biāo)就可以獲得立方體貼圖了。

所以重新寫一個(gè)反射天空盒的箱子著色器。

#version 330 corelayout(location = 0) in vec3 aPos;
layout(location =1) in vec3 aNormal;out vec3 Position;
out vec3 Normal;uniform mat4 modelMat;
uniform mat4 viewMat;
uniform mat4 projMat;void main(){Normal = mat3(transpose(inverse(modelMat)))*aNormal;Position = vec3(modelMat* vec4(aPos,1.0f));gl_Position = projMat * viewMat * modelMat*vec4(aPos,1.0f);
}#version 330 corein vec3 Position;
in vec3 Normal;out vec4 FragColor;uniform vec3 cameraPos;
uniform samplerCube skybox;void main(){vec3 viewDir = normalize(Position-cameraPos);vec3 refDir = reflect(viewDir,normalize(Normal));FragColor = vec4(texture(skybox,refDir).rgb,1.0f);
}

這里注意看下,因?yàn)槠沃餍枰ㄏ蛄啃畔?#xff0c;所以需要通過(guò)頂點(diǎn)著色器傳個(gè)normal過(guò)去,但是這里是需要經(jīng)過(guò)model變換的,也不能直接變換。所以需要通過(guò)

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

這樣才能得到正確的法向量。

然后在main中 建立新的shader,綁定VAOVBO,之后再loop中畫一個(gè)這樣的cube,記得要把camera的position傳進(jìn)去。

//反射天空盒cubeskyboxReflectShader->use();modelMat = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 5.0f));viewMat = camera.GetViewMatrix();projMat = projMat = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);glUniformMatrix4fv(glGetUniformLocation(skyboxReflectShader->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat));glUniformMatrix4fv(glGetUniformLocation(skyboxReflectShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));glUniformMatrix4fv(glGetUniformLocation(skyboxReflectShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));glUniform3f(glGetUniformLocation(skyboxReflectShader->ID, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z);glBindVertexArray(skyBoxReflectionVAO);glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);glDrawArrays(GL_TRIANGLES, 0, 36);

記得再畫之前綁定一下天空盒的材質(zhì)。

這是怎么少一個(gè)面呢,是因?yàn)槊嫣蕹脑?#xff0c;這里的頂點(diǎn)坐標(biāo)沒(méi)有按照逆時(shí)針的順序排列。

修改一下,在畫的時(shí)候把面剔除關(guān)了。

?

OK了?。

如果直接另外畫一個(gè)機(jī)器人模型,但是用這里的reflectShader的話

?這看起來(lái)非常棒,但在現(xiàn)實(shí)中大部分的模型都不具有完全反射性。我們可以引入反射貼圖(Reflection Map),來(lái)給模型更多的細(xì)節(jié)。與漫反射和鏡面光貼圖一樣,反射貼圖也是可以采樣的紋理圖像,它決定這片段的反射性。通過(guò)使用反射貼圖,我們可以知道模型的哪些部分該以什么強(qiáng)度顯示反射。在本節(jié)的練習(xí)中,將由你來(lái)為我們之前創(chuàng)建的模型加載器中引入反射貼圖,顯著提升納米裝模型的細(xì)節(jié)。

折射

折射通過(guò)refract函數(shù)實(shí)現(xiàn)。需要一個(gè)法向量,一個(gè)觀察方向,兩個(gè)材質(zhì)之間的折射率。

現(xiàn)在修改下片段著色器就好。

void main()
{             float ratio = 1.00 / 1.52;vec3 I = normalize(Position - cameraPos);vec3 R = refract(I, normalize(Normal), ratio);FragColor = vec4(texture(skybox, R).rgb, 1.0);
}

?它不太能顯示折射的效果,現(xiàn)在看起來(lái)只是有點(diǎn)像一個(gè)放大鏡。對(duì)納米裝使用相同的著色器卻能夠展現(xiàn)出了我們期待的效果:一個(gè)類玻璃的物體。

你可以想象出有了光照、反射、折射和頂點(diǎn)移動(dòng)的正確組合,你可以創(chuàng)建出非常漂亮的水。注意,如果要想獲得物理上精確的結(jié)果,我們還需要在光線離開(kāi)物體的時(shí)候再次折射,現(xiàn)在我們使用的只是單面折射(Single-side Refraction),但它對(duì)大部分場(chǎng)合都是沒(méi)問(wèn)題的。

動(dòng)態(tài)環(huán)境貼圖

現(xiàn)在我們使用的都是靜態(tài)圖像的組合來(lái)作為天空盒,看起來(lái)很不錯(cuò),但它沒(méi)有在場(chǎng)景中包括可移動(dòng)的物體。我們一直都沒(méi)有注意到這一點(diǎn),因?yàn)槲覀冎皇褂昧艘粋€(gè)物體。如果我們有一個(gè)鏡子一樣的物體,周圍還有多個(gè)物體,鏡子中可見(jiàn)的只有天空盒,看起來(lái)就像它是場(chǎng)景中唯一一個(gè)物體一樣。

通過(guò)使用幀緩沖,我們能夠?yàn)槲矬w的6個(gè)不同角度創(chuàng)建出場(chǎng)景的紋理,并在每個(gè)渲染迭代中將它們儲(chǔ)存到一個(gè)立方體貼圖中。之后我們就可以使用這個(gè)(動(dòng)態(tài)生成的)立方體貼圖來(lái)創(chuàng)建出更真實(shí)的,包含其它物體的,反射和折射表面了。這就叫做動(dòng)態(tài)環(huán)境映射(Dynamic Environment Mapping),因?yàn)槲覀儎?dòng)態(tài)創(chuàng)建了物體周圍的立方體貼圖,并將其用作環(huán)境貼圖。

雖然它看起來(lái)很棒,但它有一個(gè)很大的缺點(diǎn):我們需要為使用環(huán)境貼圖的物體渲染場(chǎng)景6次,這是對(duì)程序是非常大的性能開(kāi)銷?,F(xiàn)代的程序通常會(huì)盡可能使用天空盒,并在可能的時(shí)候使用預(yù)編譯的立方體貼圖,只要它們能產(chǎn)生一點(diǎn)動(dòng)態(tài)環(huán)境貼圖的效果。雖然動(dòng)態(tài)環(huán)境貼圖是一個(gè)很棒的技術(shù),但是要想在不降低性能的情況下讓它工作還是需要非常多的技巧的。

http://m.aloenet.com.cn/news/45521.html

相關(guān)文章:

  • 張掖市住房和城鄉(xiāng)建設(shè)局網(wǎng)站網(wǎng)絡(luò)營(yíng)銷的網(wǎng)站建設(shè)
  • 手機(jī)h5建站網(wǎng)站優(yōu)化方案模板
  • 網(wǎng)站默認(rèn)樣式表上海知名網(wǎng)站制作公司
  • 做網(wǎng)站需要編程推廣點(diǎn)擊器
  • 做影視免費(fèi)網(wǎng)站違法嗎百度官網(wǎng)網(wǎng)站登錄
  • 深圳學(xué)網(wǎng)站開(kāi)發(fā)關(guān)鍵詞挖掘站網(wǎng)
  • wordpress數(shù)據(jù)庫(kù)出錯(cuò)山東進(jìn)一步優(yōu)化
  • 佛山網(wǎng)站如何制作云南seo網(wǎng)絡(luò)優(yōu)化師
  • 中國(guó)建設(shè)委員會(huì)的官方網(wǎng)站seo免費(fèi)視頻教程
  • 醫(yī)院網(wǎng)站建設(shè)情況電商推廣平臺(tái)
  • 響應(yīng)式網(wǎng)站無(wú)法做百度聯(lián)盟最新seo操作
  • 科技網(wǎng)站實(shí)例上海seo推廣整站
  • 黃埔區(qū)做網(wǎng)站什么是互聯(lián)網(wǎng)銷售
  • 方案策劃網(wǎng)站網(wǎng)上商城網(wǎng)站開(kāi)發(fā)
  • 個(gè)人網(wǎng)站建設(shè)教程網(wǎng)站排名查詢站長(zhǎng)之家
  • 濟(jì)南網(wǎng)站建站公司東莞網(wǎng)絡(luò)營(yíng)銷推廣軟件
  • 全國(guó)網(wǎng)站制作公司排名我是seo關(guān)鍵詞
  • 網(wǎng)站優(yōu)化價(jià)格新河seo怎么做整站排名
  • 深圳做微信網(wǎng)站設(shè)計(jì)軟文推廣多少錢
  • 百度中搜到網(wǎng)站名字電商培訓(xùn)內(nèi)容
  • 如何快速做企業(yè)網(wǎng)站包括商城常見(jiàn)的營(yíng)銷方式有哪些
  • 什么是權(quán)重高的網(wǎng)站搜狗站長(zhǎng)
  • 國(guó)外獨(dú)立站建站站長(zhǎng)工具seo綜合查詢推廣
  • 廣州網(wǎng)匠營(yíng)銷型網(wǎng)站建設(shè)公司濟(jì)南網(wǎng)站seo
  • Wordpress網(wǎng)站調(diào)用代碼2024年新冠疫情最新消息今天
  • 陽(yáng)江市企業(yè)網(wǎng)站優(yōu)化企業(yè)如何進(jìn)行宣傳和推廣
  • 網(wǎng)站建設(shè)優(yōu)化服務(wù)特色高端網(wǎng)站設(shè)計(jì)
  • 重慶唐卡裝飾公司深圳市企業(yè)網(wǎng)站seo
  • 建網(wǎng)站開(kāi)源代碼全國(guó)新冠疫情最新消息
  • wordpress用戶名忘記密碼廣州seo站內(nèi)優(yōu)化