立方體貼圖通過方向向量來進(jìn)行索引/采樣。
創(chuàng)建立方體貼圖
unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
//GL_TEXTURE_CUBE_MAP_POSITIVE_X 右
//GL_TEXTURE_CUBE_MAP_NEGATIVE_X 左
//GL_TEXTURE_CUBE_MAP_POSITIVE_Y 上
//GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 下
//GL_TEXTURE_CUBE_MAP_POSITIVE_Z 后
//GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 前
//枚舉值 可以通過每次迭代加一來遍歷紋理目標(biāo)
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
);
}
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);
優(yōu)化天空盒
將觀察矩陣轉(zhuǎn)換為3x3矩陣再將其轉(zhuǎn)換回4x4矩陣可以移除位移冈绊,保留旋轉(zhuǎn)侠鳄,使視角永遠(yuǎn)處于天空盒的中心。
glm::mat4 view = glm::mat4(glm::mat3(camera.GetViewMatrix()));
在頂點(diǎn)著色器中將z設(shè)為w值死宣,使得天空盒的深度值永遠(yuǎn)是1伟恶。然后將深度函數(shù)設(shè)為GL_LEQUAL
,使得深度值小于等于1就可以測(cè)試通過毅该。這樣就可以在最后繪制天空盒且只在沒有物體的地方渲染天空盒來提升性能博秫。
void main()
{
TexCoords = aPos;
vec4 pos = projection * view * vec4(aPos, 1.0);
gl_Position = pos.xyww;
}
反射
GLSL內(nèi)建的reflect函數(shù)可以計(jì)算這個(gè)反射向量,根據(jù)鏡頭到觀察位置的向量作為入射角和法線向量使用reflect獲得反射向量,然后用反射向量采集立方體貼圖眶掌,達(dá)到環(huán)境貼圖的效果挡育。
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 Position;
uniform vec3 cameraPos;
uniform samplerCube skybox;
void main()
{
vec3 I = normalize(Position - cameraPos);
vec3 R = reflect(I, normalize(Normal));
FragColor = vec4(texture(skybox, R).rgb, 1.0);
}
折射
GLSL的內(nèi)建refract函數(shù)來實(shí)現(xiàn),它需要一個(gè)法向量朴爬、一個(gè)觀察方向和兩個(gè)材質(zhì)之間的折射率静盅。
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);
}
動(dòng)態(tài)環(huán)境貼圖
使用幀緩沖能夠?yàn)槲矬w的6個(gè)不同角度創(chuàng)建出場(chǎng)景紋理,并在每個(gè)渲染迭代中將它們儲(chǔ)存到一個(gè)立方體貼圖中寝殴。之后就可以使用動(dòng)態(tài)生成的立方體貼圖來創(chuàng)建更真實(shí)的蒿叠,包含其它物體的,反射和折射表面蚣常。但是需要為使用環(huán)境貼圖的物體渲染場(chǎng)景6次市咽,對(duì)程序是非常大的性能開銷。