关于 OpenGL 中 space 转换的困惑
A confusion about space transformation in OpenGL
在 JungHyun Han 的用于游戏编程的 3D 图形 的 book 中,第 38-39 页给出了
从e_1、e_2、e_3到u,v,n的基础变换矩阵为
然而,这与我从线性代数中了解到的相矛盾。我的意思是,基础变换矩阵不应该是该矩阵的转置吗?
注意是作者自己推导的,但是我没找到我知道的和作者做的差在哪里
代码:
顶点着色器:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
uniform vec3 cameraPosition;
uniform vec3 AT;
uniform vec3 UP;
uniform mat4 worldTrans;
vec3 ep_1 = ( cameraPosition - AT )/ length(cameraPosition - AT);
vec3 ep_2 = ( cross(UP, ep_1) )/length( cross(UP, ep_1 ));
vec3 ep_3 = cross(ep_1, ep_2);
vec4 t_ep_1 = vec4(ep_1, -1.0f);
vec4 t_ep_2 = vec4(ep_2, cameraPosition.y);
vec4 t_ep_3 = vec4(ep_3, cameraPosition.z);
mat4 viewTransform = mat4(t_ep_1, t_ep_2, t_ep_3, vec4(0.0f, 0.0f, 0.0f, 1.0f));
smooth out vec4 fragColor;
void main()
{
gl_Position = transpose(viewTransform) * position;
fragColor = color;
}
)glsl";
输入:
GLuint transMat = glGetUniformLocation(m_Program.m_shaderProgram, "worldTrans");
GLfloat dArray[16] = {0.0};
dArray[0] = 1;
dArray[3] = 0.5;
dArray[5] = 1;
dArray[7] = 0.5;
dArray[10] = 1;
dArray[11] = 0;
dArray[15] = 1;
glUniformMatrix4fv(transMat, 1, GL_TRUE, &dArray[0]);
GLuint cameraPosId = glGetUniformLocation(m_Program.m_shaderProgram, "cameraPosition");
GLuint ATId = glGetUniformLocation(m_Program.m_shaderProgram, "AT");
GLuint UPId = glGetUniformLocation(m_Program.m_shaderProgram, "UP");
const float cameraPosition[4] = {2.0f, 0.0f, 0.0f};
const float AT[4] = {1.0f, 0.0f, 0.0f};
const float UP[4] = {0.0f, 0.0f, 1.0f};
glUniform3fv(cameraPosId, 1, cameraPosition);
glUniform3fv(ATId, 1, AT);
glUniform3fv(UPId, 1, UP);
虽然旋转、缩放或变形确实可以用 4x4 矩阵表示为以下形式
你正在阅读的是所谓的"View Transformation"
为了实现这个矩阵我们需要两个变换:首先平移到相机位置,然后旋转相机。
进行这些转换的数据是:
- 相机位置
C
(Cx,Cy,Cz)
- 目标位置
T
(Tx,Ty,Tz)
- 相机向上归一化
UP
(Ux、Uy、Uz)
翻译可以表示为
对于旋转我们定义:
F = T – C
归一化后我们得到 f = F / ||T-C||
,也用 f= normalize(F)
表示
s = normalize(cross (f, UP))
u = normalize(cross(s, f))
s, u, -f
是旧坐标系中表示的新坐标轴。
因此我们可以为这个变换建立旋转矩阵
将两个变换组合在一个唯一的矩阵中,我们得到:
注意轴系是OpenGL使用的轴系,其中-f= cross(s,u)
.
现在,与您的 GLSL 代码相比,我看到:
- 您的
f
(ep_1) 矢量方向相反。
s
(ep_2) 向量计算为 cross(UP, f)
而不是 cross(f, UP)
。这是对的,因为 1).
- 与
u
(ep_3) 相同。
V
单元格 (0,0) 的构建错误。它试图通过使用 -1.0f
. 来设置正确的方向
- 对于其他单元格(t_ep_J 组件),使用相机位置。但是你忘了用它的 点积 和
s,u,f
.
- GLSL 初始化器
mat4(c1,c2,c3,c4)
需要列向量作为参数。你通过了行列。但是,之后,在 main
中使用 transpose
纠正了它。
附带说明一下,您不会为每个顶点、时间、时间和时间计算矩阵……对吗?最好在 CPU 侧计算它并将 if(按列顺序)作为统一传递。
显然,向量中基的变化 space 确实会改变该向量中的向量 space,这不是我们想要的。
因此,我所应用的数学在这里无效。
要详细了解为什么我们使用我在问题中给出的矩阵,请参阅this问题。
在 JungHyun Han 的用于游戏编程的 3D 图形 的 book 中,第 38-39 页给出了
从e_1、e_2、e_3到u,v,n的基础变换矩阵为
然而,这与我从线性代数中了解到的相矛盾。我的意思是,基础变换矩阵不应该是该矩阵的转置吗?
注意是作者自己推导的,但是我没找到我知道的和作者做的差在哪里
代码: 顶点着色器:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;
uniform vec3 cameraPosition;
uniform vec3 AT;
uniform vec3 UP;
uniform mat4 worldTrans;
vec3 ep_1 = ( cameraPosition - AT )/ length(cameraPosition - AT);
vec3 ep_2 = ( cross(UP, ep_1) )/length( cross(UP, ep_1 ));
vec3 ep_3 = cross(ep_1, ep_2);
vec4 t_ep_1 = vec4(ep_1, -1.0f);
vec4 t_ep_2 = vec4(ep_2, cameraPosition.y);
vec4 t_ep_3 = vec4(ep_3, cameraPosition.z);
mat4 viewTransform = mat4(t_ep_1, t_ep_2, t_ep_3, vec4(0.0f, 0.0f, 0.0f, 1.0f));
smooth out vec4 fragColor;
void main()
{
gl_Position = transpose(viewTransform) * position;
fragColor = color;
}
)glsl";
输入:
GLuint transMat = glGetUniformLocation(m_Program.m_shaderProgram, "worldTrans");
GLfloat dArray[16] = {0.0};
dArray[0] = 1;
dArray[3] = 0.5;
dArray[5] = 1;
dArray[7] = 0.5;
dArray[10] = 1;
dArray[11] = 0;
dArray[15] = 1;
glUniformMatrix4fv(transMat, 1, GL_TRUE, &dArray[0]);
GLuint cameraPosId = glGetUniformLocation(m_Program.m_shaderProgram, "cameraPosition");
GLuint ATId = glGetUniformLocation(m_Program.m_shaderProgram, "AT");
GLuint UPId = glGetUniformLocation(m_Program.m_shaderProgram, "UP");
const float cameraPosition[4] = {2.0f, 0.0f, 0.0f};
const float AT[4] = {1.0f, 0.0f, 0.0f};
const float UP[4] = {0.0f, 0.0f, 1.0f};
glUniform3fv(cameraPosId, 1, cameraPosition);
glUniform3fv(ATId, 1, AT);
glUniform3fv(UPId, 1, UP);
虽然旋转、缩放或变形确实可以用 4x4 矩阵表示为以下形式
你正在阅读的是所谓的"View Transformation"
为了实现这个矩阵我们需要两个变换:首先平移到相机位置,然后旋转相机。
进行这些转换的数据是:
- 相机位置
C
(Cx,Cy,Cz) - 目标位置
T
(Tx,Ty,Tz) - 相机向上归一化
UP
(Ux、Uy、Uz)
翻译可以表示为
对于旋转我们定义:
F = T – C
归一化后我们得到 f = F / ||T-C||
,也用 f= normalize(F)
表示
s = normalize(cross (f, UP))
u = normalize(cross(s, f))
s, u, -f
是旧坐标系中表示的新坐标轴。
因此我们可以为这个变换建立旋转矩阵
将两个变换组合在一个唯一的矩阵中,我们得到:
注意轴系是OpenGL使用的轴系,其中-f= cross(s,u)
.
现在,与您的 GLSL 代码相比,我看到:
- 您的
f
(ep_1) 矢量方向相反。 s
(ep_2) 向量计算为cross(UP, f)
而不是cross(f, UP)
。这是对的,因为 1).- 与
u
(ep_3) 相同。 V
单元格 (0,0) 的构建错误。它试图通过使用-1.0f
. 来设置正确的方向
- 对于其他单元格(t_ep_J 组件),使用相机位置。但是你忘了用它的 点积 和
s,u,f
. - GLSL 初始化器
mat4(c1,c2,c3,c4)
需要列向量作为参数。你通过了行列。但是,之后,在main
中使用transpose
纠正了它。
附带说明一下,您不会为每个顶点、时间、时间和时间计算矩阵……对吗?最好在 CPU 侧计算它并将 if(按列顺序)作为统一传递。
显然,向量中基的变化 space 确实会改变该向量中的向量 space,这不是我们想要的。
因此,我所应用的数学在这里无效。
要详细了解为什么我们使用我在问题中给出的矩阵,请参阅this问题。