[英]OpenGL reflection not mapping skybox correctly
我試圖在不使用 LearnOpenGL 方法的情況下學習 OpenGL 上的反射,但我無法弄清楚反射有什么問題。 相機視圖的某些部分似乎發生了某種扭曲和翻轉。 到目前為止,我只是使用視圖矩陣來簡化代碼。
這就是球體反射的樣子。
我也嘗試使用立方體。 即使我的鼠標繼續向右移動,反射也會扭曲,然后最終顯示扭曲之前存在的圖像。
立方體反射
天空盒圖像
這是天空盒頂點着色器
#version 330 core
layout (location = 0) in vec3 aPos;
out vec3 o_pos;
void main()
{
o_pos = aPos;
gl_Position = vec4(aPos, 1.0);
}
這是天空盒片段着色器。 我將視圖矩陣直接傳遞給片段着色器。
#version 330 core
out vec4 FragColor;
in vec3 o_pos;
uniform vec3 view_up;
uniform vec3 view_right;
uniform vec3 view_forward;
uniform samplerCube cubeTex;
void main()
{
vec3 pv = mat3(view_right, view_up, view_forward) * vec3(o_pos.xy, 1.0);
FragColor = vec4(texture(cubeTex, pv).rgb, 1.0);
}
這是對象頂點着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 normal;
out vec3 o_normal;
out vec3 o_pos;
void main()
{
o_pos = aPos;
o_normal = normal;
gl_Position = vec4(o_pos, 1.0f);
}
這是對象片段着色器。 它類似於 learnopengl 着色器。
#version 330 core
in vec3 o_pos;
in vec3 o_normal;
out vec4 fragColor;
uniform vec3 eye_pos;
uniform samplerCube cubeTex;
void main()
{
vec3 incident = normalize(o_pos - eye_pos);
vec3 reflection = reflect(incident, normalize(o_normal));
fragColor = vec4(texture(cubeTex, reflection).rgb, 1.0);
}
這是渲染循環
while (!glfwWindowShouldClose(window))
{
// input
processInput(window);
// render
glClearColor(0.9f, 0.8f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// change view using mouse input
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
ypos = (ypos/SCR_HEIGHT) * PI * PI * 0.5;
xpos = (xpos/SCR_WIDTH) * 2 * PI - PI;
if (ypos < PI/2) ypos = 1.6f;
if (ypos > 3*PI/2) ypos = 4.7f;
eye_forward = normalize(glm::vec3{(GLfloat)(cos(ypos) * cos(xpos)),
(GLfloat)sin(ypos),
(GLfloat)(cos(ypos) * sin(xpos))});
eye_right = glm::normalize(glm::cross(eye_forward, glm::vec3{0.0, 1.0, 0.0}));
eye_up = glm::cross(eye_right, eye_forward);
// draw skybox
glUseProgram(shaderProgram);
glUniform1i(u_cubeTex, 0);
glUniform3fv(u_view_up, 1, (GLfloat*)&eye_up);
glUniform3fv(u_view_right, 1, (GLfloat*)&eye_right);
glUniform3fv(u_view_forward, 1, (GLfloat*)&eye_forward);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, cube.size());
// draw UV sphere
glUseProgram(sphereProgram);
glUniform1i(u_cubeTex2, 0);
glUniform3fv(u_eye_pos, 1, (GLfloat*)&eye_forward);
glBindVertexArray(sphereVAO);
glDrawArrays(GL_TRIANGLE, 0, sphere.size());
glfwSwapBuffers(window);
glfwPollEvents();
}
eye_pos
是世界空間中的一個位置。
o_pos
是視圖空間、剪輯空間和標准化設備空間中的位置。 這在您的情況下完全相同,因為您沒有投影矩陣,並且頂點坐標屬性直接分配給頂點着色器中的剪輯空間位置:
gl_Position = vec4(aPos, 1.0);
無論如何,計算從世界空間位置到視圖空間位置的向量沒有任何意義,因為您這樣做:
vec3 incident = normalize(o_pos - eye_pos);
視圖空間中的眼睛位置為 (0, 0, 0)。 所以視圖空間中的事件視圖向量是:
vec3 incident = normalize(o_pos - vec3(0.0, 0.0, 0.0));
這個向量必須從視圖空間轉換到世界空間,這可以通過視圖的方向矩陣( mat3(view_right, view_up, view_forward)
)來實現,就像你在天空盒片段着色器中做的那樣:
vec3 incident = mat3(view_right, view_up, view_forward) * normalize(o_pos);
法線向量o_normal
也是一個視圖空間向量。 所以它必須轉換到世界空間:
vec3 wordlNormal = mat3(view_right, view_up, view_forward) * normalize(o_normal);
除了變換入射向量和法向量,還可以變換反射后的結果向量。
您必須更改對象片段着色器,以解決您的問題:
#version 330 core
in vec3 o_pos;
in vec3 o_normal;
out vec4 fragColor;
uniform vec3 view_up;
uniform vec3 view_right;
uniform vec3 view_forward;
uniform samplerCube cubeTex;
void main()
{
mat3 invNormalM = mat3(view_right, view_up, view_forward);
vec3 viewIncident = normalize(o_pos);
vec3 viewNormal = normalize(o_normal);
vec3 worldReflection = invNormalM * reflect(viewIncident, viewNormal);
fragColor = vec4(texture(cubeTex, worldReflection).rgb, 1.0);
}
我將視圖矩陣直接傳遞給片段着色器。
mat3(view_right, view_up, view_forward)
不是視圖矩陣。 它是相機的方向矩陣。 所以它是逆視圖(正常)矩陣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.