[英]OpenGL cubemap face order & sampling issue
我有一個基於 SDL2 和 OpenGL(3.3 核心配置文件)的渲染器,它給了我關於轉換和紋理(2D)的預期結果。
但是,當我嘗試使用從這些紋理創建的立方體貼圖來顯示天空盒時(盡管我也嘗試過其他人),該過程中有兩個步驟,我遇到的其他教程或示例似乎不需要這樣做,我無法解釋:
1、上傳時上下面要互換,即:上一張是GL_TEXTURE_CUBEMAP_NEGATIVE_Y
,下一張是GL_TEXTURE_CUBEMAP_POSITIVE_Y
; 2、在對立方體貼圖進行采樣時,我必須沿y反轉頂點位置,還要沿z反轉;
沒有這個,我得到以下結果:
(注意左下遠頂點縮放了 0.8 以說明我的坐標系是正確的)
圖像文件命名正確。
立方體是我正在執行的唯一繪制。
如果我刪除任何邊的 [索引],我會得到預期的結果(即沒有交換/鏡像)。
我的集成和專用 GPU 似乎得到了相同的結果。
我的 OpenGL 常量,來自glLoadGen (最初)生成的標頭:
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
貼圖上傳代碼(和LearnOpenGL的教程差不多):
GLuint name;
glGenTextures(1, &name);
glBindTexture(GL_TEXTURE_CUBE_MAP, name);
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLint target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
for (uint8_t i = 0; i < 6; ++i)
{
glTexImage2D(target + i, 0, GL_RGB8, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, pixelData[i]));
}
頂點着色器:
#version 330
precision mediump float;
uniform mat4 uModelViewProjection;
in vec3 aPosition;
out vec3 vTexCoord;
void main()
{
vec4 position = uModelViewProjection * vec4(aPosition, 1.f);
gl_Position = position.xyww;
vTexCoord = aPosition;
}
片段着色器:
#version 330
precision mediump float;
uniform samplerCube uTexture0;
in vec3 vTexCoord;
out vec4 FragColor;
void main()
{
FragColor = texture(uTexture0, vTexCoord);
// using textureCube() yields a compile error asking for #extension GL_NV_shadow_samplers_cube : enable, but even with that, the issue perists.
}
網格設置(半偽代碼):
// 4----5
// /| /|
// 6----7 |
// | | | |
// | 0--|-1
// |/ |/
// 2----3
VertexType vertices[8] = {
Vector3(-1.f, -1.f, -1.f) * .8f, // debug coordinate system
Vector3(1.f, -1.f, -1.f),
Vector3(-1.f, -1.f, 1.f),
Vector3(1.f, -1.f, 1.f),
Vector3(-1.f, 1.f, -1.f),
Vector3(1.f, 1.f, -1.f),
Vector3(-1.f, 1.f, 1.f),
Vector3(1.f, 1.f, 1.f),
};
uint16_t indices[] = {
4, 0, 5,
0, 1, 5,
6, 2, 4,
2, 0, 4,
7, 3, 6,
3, 2, 6,
5, 1, 7,
1, 3, 7,
0, 2, 1,
2, 3, 1,
5, 7, 4,
7, 6, 4,
};
// create buffers & upload data
渲染(偽代碼):
// -clear color & depth buffers;
// -set the model transform to a translation of -10 units along z;
// view transform is identity; projection is perspective with .25
// radians vertical FOV, zNear of .1, zFar of 100.; viewport is full screen
// -set shader program;
// -bind texture (same name, same target as upon uploading);
// -enable backface culling only (no depth test / write);
// -draw the cube
// -glFlush() and swap buffers;
究竟是什么導致了上述兩個問題?
該問題是由.str
紋理坐標到立方體貼圖的映射引起的:
OpenGL 4.6 API 核心配置文件規范,8.13 立方體貼圖紋理選擇,第 253 頁:
當對立方體貼圖紋理進行采樣時, (s, t, r)紋理坐標被視為從立方體中心發出的方向向量(rx, ry, rz) 。 q坐標被忽略。 在紋理應用時,內插的每片段方向向量基於最大量級坐標方向(長軸方向)選擇立方體貼圖面的二維圖像之一。 如果兩個或更多坐標具有相同的大小,則實現可以定義規則來消除這種情況的歧義。 該規則必須是確定性的,並且僅取決於(rx, ry, rz) 。 表 8.19 中的目標列解釋了主軸方向如何映射到特定立方體貼圖目標的二維圖像。 使用由表 8.19 中指定的主軸方向確定的sc 、 tc和ma ,更新的(s, t)計算如下:
s = 1/2 (sc / |m_a| + 1)
t = 1/2 (tc / |m_a| + 1)
Major Axis Direction| Target |sc |tc |ma | --------------------+---------------------------+---+---+---+ +rx |TEXTURE_CUBE_MAP_POSITIVE_X|−rz|−ry| rx| −rx |TEXTURE_CUBE_MAP_NEGATIVE_X| rz|−ry| rx| +ry |TEXTURE_CUBE_MAP_POSITIVE_Y| rx| rz| ry| −ry |TEXTURE_CUBE_MAP_NEGATIVE_Y| rx|−rz| ry| +rz |TEXTURE_CUBE_MAP_POSITIVE_Z| rx|−ry| rz| −rz |TEXTURE_CUBE_MAP_NEGATIVE_Z|−rx|−ry| rz| --------------------+---------------------------+---+---+---+
表 8.19:基於紋理坐標長軸方向的立方體貼圖圖像選擇
旋轉可以通過在將 6 個立方體貼圖圖像加載到立方體貼圖采樣器之前旋轉它們或通過旋轉紋理坐標來實現。
立方體貼圖用作場景中的環境貼圖,紋理坐標通過方向向量獲得,然后旋轉圖像是有意義的。 如果立方體貼圖包裹在網格上,則可以以正確的方式指定紋理坐標。
上一個答案的推理來自引用的規范。 文字有誤。
正在發生的事情是,如果您仔細查看數學,引用的文本要求立方體貼圖的圖像具有自上而下的方向,並在 +Y 向上的左手坐標系中排列。 這意味着+Y 處的天空,如果您面向+Z,則-X 應在您的左側,+X 應在您的右側。 這顯然是從立方體貼圖首次出現的 Renderman 繼承的。
您作為天空盒渲染的立方體的坐標將用於采樣立方體貼圖,位於 OpenGL 的坐標系中,該坐標系是右手坐標系。 這些必須在采樣前轉換為立方體貼圖的左手系。 這是通過簡單地將 Z 坐標縮放 -1 來完成的。 不這樣做意味着場景將是它應該是什么的鏡像。 我看過的樣本中一個非常常見的失敗。
OP 顛倒圖像是因為它們具有標准的 OpenGL 自底向上方向。
如果您使用的是 Vulkan,則它具有左手系統,但 Y 已關閉。 因此,要在 Vulkan 上正確渲染立方體貼圖,您仍然需要轉換天空盒立方體的坐標,在這種情況下,將它們繞 X 軸旋轉 180°。 否則,您將獲得顛倒的圖像。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.