我正在尝试在我的
pyopengl
项目中实现阴影贴图,但矩阵计算出现问题。 “太阳”的视图始终来自坐标 x: 0、y: 0、z: 0,渲染距离为 1
,与从 0 到 1 的黑白值相关。
如果我删除
mvp_matrix
和 model_matrix
的乘法并仅将 model_matrix
传递给着色器,则会产生相同的输出,所以出现了问题
以下是我的矩阵的创建方式:
def update_light_view_matrix(self, direction: vec3, center: vec3) -> None:
"""
Updates the "view" matrix of the light. This creates a view matrix which
will line up the direction of the "view cuboid" with the direction of the
light. The light itself has no position, so the "view" matrix is centered
at the center of the "view cuboid". The created view matrix determines
where and how the "view cuboid" is positioned in the world. The size of
the view cuboid, however, is determined by the projection matrix.
:param direction: the light direction, and therefore the direction that the "view cuboid" should be pointing.
:param center: the center of the "view cuboid" in world space.
:return:
"""
direction = direction.normalize()
self.__light_view_matrix = mat4().identity()
pitch = math.acos(math.sqrt(direction.x**2 + direction.z**2))
self.__light_view_matrix = self.__light_view_matrix.rotate(pitch, vec3(1, 0, 0))
yaw = math.degrees(math.atan(direction.x / direction.z))
yaw = yaw - 180 if direction.z > 0 else yaw
self.__light_view_matrix = self.__light_view_matrix.rotate(-math.radians(yaw), vec3(0, 1, 0))
self.__light_view_matrix = self.__light_view_matrix.translate(-center)
def update_ortho_projection_matrix(self, width: float, height: float, length: float) -> None:
"""
Creates the orthographic projection matrix. This projection matrix
basically sets the width, length and height of the "view cuboid", based
on the values that were calculated in the ShadowBox class.
:param width: shadow box width.
:param height: shadow box height.
:param length: shadow box length.
:return:
"""
self.__projection_matrix = mat4()
self.__projection_matrix[(0, 0)] = 2.0 / width
self.__projection_matrix[(1, 1)] = 2.0 / height
self.__projection_matrix[(2, 2)] = -2.0 / length
self.__projection_matrix[(3, 3)] = 1
模型矩阵绝对正确。
...
self.__projection_view_matrix = self.__projection_matrix * self.__light_view_matrix
...
mvp_matrix = self.__projection_view_matrix * model_matrix
我想我会添加矩阵计算的输出,以便您可以验证它们:
projection_matrix:
[ 0.0036, 0.0000, 0.0000, 0.0000]
[ 0.0000, 0.0069, 0.0000, 0.0000]
[ 0.0000, 0.0000, -0.0128, 0.0000]
[ 0.0000, 0.0000, 0.0000, 1.0000]
light_view_matrix:
[ -0.7071, 0.0000, -0.7071, -15.1670]
[ -0.5145, 0.6860, 0.5145, 22.6592]
[ 0.4851, 0.7276, -0.4851, 1.9242]
[ 0.0000, 0.0000, 0.0000, 1.0000]
projection_view_matrix:
[ -0.0026, 0.0000, -0.0026, -0.0552]
[ -0.0035, 0.0047, 0.0035, 0.1560]
[ -0.0062, -0.0093, 0.0062, -0.0245]
[ 0.0000, 0.0000, 0.0000, 1.0000]
mvp_matrix:
[ 1.0000, 0.0000, 0.0000, 601.0000]
[ 0.0000, 1.0000, 0.0000, -1.5510]
[ 0.0000, 0.0000, 1.0000, 778.0000]
[ 0.0000, 0.0000, 0.0000, 1.0000]
“错误”在于在代码中计算模型-视图-投影矩阵,而不是在顶点着色器中计算。
pycgtypes
库声明它与 OpenGL 兼容,尽管事实并非如此,并且计算出的矩阵是错误的。
将 3 个独立的矩阵加载到顶点着色器中并计算
mvp_matrix
即可解决问题。
#version 150
in vec3 in_position;
uniform mat4 light_view_matrix;
uniform mat4 projection_matrix;
uniform mat4 model_matrix;
void main(void){
mat4 mvp_matrix = projection_matrix * light_view_matrix * model_matrix;
gl_Position = mvp_matrix * vec4(in_position, 1.0);
}