Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于平铺渲染的OpenGL矩阵设置_Opengl_Matrix_Tile - Fatal编程技术网

用于平铺渲染的OpenGL矩阵设置

用于平铺渲染的OpenGL矩阵设置,opengl,matrix,tile,Opengl,Matrix,Tile,读完后,我试图实现他的解决方案。源图像如下所示(800 x 600) 生成的图像有2x2个分幅,每个分幅为800 x 600,每个分幅如下所示 正如你所看到的,它们并不完全匹配,尽管我可以看到一些模糊有趣的事情发生了。我肯定我在某处犯了一个基本错误,但我看不太清楚 我做了4次传球,其中: w, h are 2,2 (2x2 tiles) x, y are (0,0) (1,0) (0,1) and (1,1) in each of the 4 passes MyFov is

读完后,我试图实现他的解决方案。源图像如下所示(800 x 600)

生成的图像有2x2个分幅,每个分幅为800 x 600,每个分幅如下所示

正如你所看到的,它们并不完全匹配,尽管我可以看到一些模糊有趣的事情发生了。我肯定我在某处犯了一个基本错误,但我看不太清楚

我做了4次传球,其中:

w, h are 2,2 (2x2 tiles)    
x, y are (0,0) (1,0) (0,1) and (1,1) in each of the 4 passes    
MyFov is 1.30899692 (75 degrees)
MyWindowWidth, MyWindowHeight are 800, 600
MyNearPlane, MyFarPlane are 0.1, 200.0
计算每个平铺的平截体的算法为:

auto aspect = static_cast<float>(MyWindowWidth) / static_cast<float>(MyWindowHeight);
auto right = -0.5f * Math::Tan(MyFov) * MyShaderData.Camera_NearPlane;
auto left = -right;
auto top = aspect * right;
auto bottom = -top;
auto shift_X = (right - left) / static_cast<float>(w);
auto shift_Y = (top - bottom) / static_cast<float>(h);
auto frustum = Math::Frustum(left   + shift_X * static_cast<float>(x),
                             left   + shift_X * static_cast<float>(x + 1), 
                             bottom + shift_Y * static_cast<float>(y),
                             bottom + shift_Y * static_cast<float>(y + 1),
                             MyShaderData.Camera_NearPlane,
                             MyShaderData.Camera_FarPlane);
有人能发现我的错误吗

编辑

所以德哈斯向我解释了这一点——一种更简单的方法是简单地缩放和转换投影矩阵。为了进行测试,我修改了我的翻译矩阵,按2倍的比例放大,如下所示(更改每个瓷砖的翻译):

auto-scale=Math::scale(2.f,2.f,1.f);
自动翻译=数学::翻译(0.5f,0.5f,0.f);
自动投影=数学::透视(MyFov,
静态投影(MyWindowWidth)/静态投影(MyWindowHeight),
MyShaderData.Camera_近平面,
MyShaderData.摄像机(飞机);
MyShaderData.Camera_Projection=缩放*平移*投影;
生成的图像如下(将4拼接在一起)-图像中的不连续性是由后处理引起的,因此这是我可能在某个时候必须处理的另一个问题


这不是这个问题的真正答案,但它可能是解决您在这里试图解决的问题的一种有用的替代方法。在我看来,datenwolf在回答你所指的问题时所提出的解决方案比需要的更为复杂。所以我在这里介绍我的选择

例如:我假设标准的OpenGL矩阵约定,因此矩阵
M
的顶点变换是按照
v'=M*v
的方式进行的(就像固定函数管道那样)

当使用某个投影矩阵
p
渲染场景时,可以通过在应用投影矩阵后应用缩放和变换操作来提取所述场景的任何轴对齐子矩形

关键的一点是,查看体积定义为NDC空间中的[-1,1]^3立方体。剪辑空间(即
P
将数据转换为的内容)就是该卷的同质表示。由于典型的
4x4
变换矩阵都在同质空间中工作,因此我们根本不需要关心
w
,只需像在NDC空间中一样定义变换即可

因为您只需要一些2D平铺,
z
应该保持原样,并且只需要在
x
y
中进行一些缩放和平移。当将变换
A
B
组合成单个矩阵
C
C=A*B
时,遵循上述约定,这将导致首先应用
B
,最后应用
A
(因为
C*v==A*B*v==A*(B*v)
)。因此,为了修改投影后的结果,我们必须将一些变换预乘到
P
,我们完成了:

P'=S(sx,sy,1) * T(tx,ty,0) * P
p'
的构造将使用任何有效的投影矩阵
p
,无论它是透视变换还是正交变换。在ortho的例子中,这是非常清楚的。在透视的情况下,这实际上修改了视野,并将平截头体移动到非对称的位置

当您要将图像平铺到由
m
n
段组成的网格中时。很明显,
sx=m
sy=n
。正如我使用的
S*T
顺序(选择)一样,
T
在缩放之前应用,因此对于每个磁贴,
(tx,ty)
只是将磁贴中心移动到新中心(即原点)的向量。由于NDC空间的宽度和高度为2个单位,因此对于平铺
x,y
,转换为

tx= - (-1 + 2/(2*m) + (2/m) * x)
ty= - (-1 + 2/(2*n) + (2/n) * y)
//     ^     ^         ^    
//     |     |         |
//     |     |         +- size of of each tile in NDC space
//     |     |
//     |     +- half the size (as the center offset)
//     |
//     +- left/bottom border of NDC space

我还没有检查您的实现中出现了什么问题,但我认为DatenWalf的解决方案存在不必要的复杂性。如果使用某个投影矩阵渲染某个场景(无论是正交还是透视),生成的平截头体最终将以[-1,1]^3 NDC空间的同质表示形式结束。因此,如果你想要渲染的全屏的一些平铺,只需在x和y方向上预先乘以一些比例和平移,就足以选择你喜欢的任何2D子矩形(这将产生与在透视截锥体中改变FOV和不对称性相同的效果)。我认为NDC发生在同质分割之后,这是在投影矩阵相乘之后,所以我看不出它是如何工作的。不管怎样,我尝试了WxH规模的预乘和各种不同的翻译,但我无法让它工作。数学是错误的。我建议的应用于剪辑空间。我只在截锥体的[-1,1]范围内使用NDC。关键点在于,在应用投影矩阵(这意味着按照默认GL约定将其预乘)后,应用简单的平移和缩放,以缩放[-1,1]的某个子矩形并将其移动到整个[-1,1]范围,将准确地获得整个视口中的图像部分。例如,如果您想要通过应用矩阵
P
得到的图像的左上四分之一,您可以简单地使用
P'=S(2,2,1)*T(0.5,-0.5,0)*P
(其中
S
是一个比例矩阵,
T
是一个翻译)来替代
P
(无论P是哪种投影,它在任何情况下都会起作用)。所有这些都假设您使用GL的常用矩阵约定,因此顶点的变换
v
v'=M*v
。如果您使用
v'=M*v
,则将修改后的内容相乘是正确的方法。啊,我只花了2天时间就“获得了”。请加上这个作为答案,这样我可以给你一些分数。我将编辑我的问题以显示r
auto scale = Math::Scale(2.f, 2.f, 1.f);
auto translate = Math::Translate(0.5f, 0.5f, 0.f);
auto projection = Math::Perspective(MyFov,
                                    static_cast<float>(MyWindowWidth) / static_cast<float>(MyWindowHeight),
                                    MyShaderData.Camera_NearPlane,
                                    MyShaderData.Camera_FarPlane);          

MyShaderData.Camera_Projection = scale * translate * projection;
P'=S(sx,sy,1) * T(tx,ty,0) * P
tx= - (-1 + 2/(2*m) + (2/m) * x)
ty= - (-1 + 2/(2*n) + (2/n) * y)
//     ^     ^         ^    
//     |     |         |
//     |     |         +- size of of each tile in NDC space
//     |     |
//     |     +- half the size (as the center offset)
//     |
//     +- left/bottom border of NDC space