知乎上一篇很好的文章:反向Z(Reversed-Z)的深度缓冲原理 - 知乎
先只考虑投影后裁剪空间的深度坐标 z 范围,有:
也就是说,OpenGL 平台的投影矩阵会和其它平台不一样,而几篇经典的文章(一个例子)都是推的 OpenGL 的投影矩阵:
而对应 D3D 等其它平台的投影矩阵为
当然投影矩阵还会跟参考坐标系有关系,例如 OpenGL 使用的是右手坐标系,但是在NDC中使用的是左手坐标系,因此构造投影矩阵时,需要将 near 和 far 取负
而如今的游戏中,往往会使用近处 1.0,远处 0.0 的深度分布,Unity 引擎中,某些 Graphics API 上会默认开启这样的改动,这一块可以直接参考官方手册:
使用反向 z 的好处是可以均匀深度值 z 的精度,使得无论接近近裁平面还是远裁平面,精度都能得到一定的保证:这主要是从这两点考量的:
而反向 Z 就可以完美的使这两个性质做到互补,而非要不都满足精度高的条件,要不都不满足以带来更大的精度不平衡
Unity shader 开发时,在使用深度发生反转的平台上的着色器满足条件:
因此如果要手动提取深度缓冲区值,则可能需要检查缓冲区方向
float z = tex2D(_CameraDepthTexture, uv);
# if defined(UNITY_REVERSED_Z)
z = 1.0f - z;
# endif
如果你想自己计算投影矩阵,就要非常小心了,如果处于反向 Z 的平台上,则 GL.GetGPUProjectionMatrix() 输入当前矩阵可以给你提供一个还原反向 Z 的矩阵,但如果要手动从投影矩阵中进行合成(例如,对于自定义阴影或深度渲染),则需要通过脚本按需自行还原深度 方向
当然还会有一些情况:比如我的深度需要用于参与计算,而非用于深度检测,这时就需要你指定一个正确的投影矩阵,并且要求是一个平台无关的投影矩阵,就像下面这个例子一样:
// 无视平台的转换投影矩阵到GL格式
private static Matrix4x4 GetGPUProjMatrix(Matrix4x4 p)
{
p[2, 0] = p[2, 0] * (-0.5f) + p[3, 0] * 0.5f;
p[2, 1] = p[2, 1] * (-0.5f) + p[3, 1] * 0.5f;
p[2, 2] = p[2, 2] * (-0.5f) + p[3, 2] * 0.5f;
p[2, 3] = p[2, 3] * (-0.5f) + p[3, 3] * 0.5f;
return p;
}
public static void GetShadowMatrix(Vector2 size, Vector2 worldHeight, Vector2 worldOffset, Vector2 lightDirection, out Matrix4x4 m, out Matrix4x4 p)
{
m = Matrix4x4.TRS(new Vector3(-size.x * 0.5f + worldOffset.x, -size.y * 0.5f + worldOffset.y, 0.0f), Quaternion.Euler(-90, 0, 0), Vector3.one);
p = Matrix4x4.Ortho(-size.x * 0.5f, size.x * 0.5f, -size.y * 0.5f, size.y * 0.5f, worldHeight.x, worldHeight.y);
float z = Mathf.Sqrt(1 - lightDirection.x * lightDirection.x - lightDirection.y * lightDirection.y);
p[0, 2] = -(lightDirection.x/z) / size.x * 2.0f;
p[1, 2] = -(lightDirection.y/z) / size.y * 2.0f;
// ESM 的阴影是在DX11下烘焙的 这里将ESM_Matrix转换成了GL的矩阵格式
// GLES3.0 的绘制模式下没有做翻转,但是实际需要使用翻转后的矩阵
// GL.GetGPUProjectionMatrix 接口只会转DX到GL 遇到GL时直接不做处理
// 为了平台数据一致 直接统一转换
// p = GL.GetGPUProjectionMatrix(p, false);
p = GetGPUProjMatrix(p);
}
由于 Matrix4x4.Ortho 函数返回的投影矩阵默认裁剪后 z 范围为 [-1, 1],并且不会考虑反向 Z,因此如果你想使最后深度在 [0, 1] 的范围内,就需要自行进行转换,由于深度计算和平台无关,因此不能直接调用 GL.GetGPUProjectionMatrix() ,它在 OpenGL 平台上会不起作用
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。
在我的应用程序中我有classUserincludeUser::FooendUser::Foo定义在app/models/user/foo.rb现在我正在使用一个定义了自己的Foo类的库。我收到此错误:warning:toplevelconstantFooreferencedbyUser::FooUser仅引用具有完整路径的Foo,User::Foo,而Foo实际上从来没有指的是Foo。这是怎么回事?更新:才想起我之前遇到过同样的问题,在问题1中看到这里:HowdoIrefertoasubmodule's"fullpath"inruby? 最佳答案
考虑Ruby类Foo::Bar。惯例是将“Foo”命名空间作为一个模块,但它也可以很容易地作为一个类:moduleFoo;classBar;end;end对比:classFoo;classBar;end;end在第二种情况下,Bar不是Foo的内部类,它只是在Foo的单例上定义的另一个常量。在这两种情况下,父类(superclass)都是Object并且它们只包含Kernel模块。它们的祖先链是相同的。因此,除了您可以根据其类使用Foo进行的操作(如果是类则实例化,如果是模块则扩展/包含),命名空间的性质是否对有任何影响酒吧?是否有令人信服的理由选择其中一个名称间距而不是另一个?我看到
我在将模块包含在命名空间类中时遇到问题。下面的示例抛出错误uninitializedconstantBar::Foo::Baz(NameError)。我在这里缺少哪些基本的Ruby知识?moduleFoomoduleBazdefhelloputs'hello'endendendmoduleBarclassFooincludeFoo::Bazendendfoo=Bar::Foo.new 最佳答案 使用::强制查找到顶层:moduleBarclassFooinclude::Foo::Bazendend
我想为类定义Fabricator,其命名空间类似于“Foo::Bar”。告诉我它的工作方式。这是我的代码。模型/foo.rbclassFooincludeMongoid::Documentembedded_in:foo_container,polymorphic:truefield:xxx....end模型/foo/bar.rbclassFoo::Bar数据/制造商/foo_bar_fabricator.rbFabricator(:foo_bar,class_name:'Foo::Bar')doyyy'MyString'zzz'MyString'end当我尝试在parino控制台上创建
一、习惯约定图片来自PSINS(高精度捷联惯导算法)PSINS工具箱入门与详解.pptx二、基本旋转矩阵绕x轴逆时钟旋转α\alphaα角度Rx(α)=[ 1000cosαsinα0−sinαcosα]R_x(\alpha)=\begin{bmatrix}\1&0&0\\0&\cos\alpha&\sin\alpha\\0&-\sin\alpha&\cos\alpha\end{bmatrix}Rx(α)= 1000cosα−sinα0sinαcosα绕y轴逆时钟旋转α\alphaα角度Ry(α)=[ cosα0−sinα010sinα0cosα]R_y(\alpha
欧拉角、旋转矩阵及四元数1.简介2.欧拉角2.1欧拉角定义2.2右手系和左手系2.3转换流程3.旋转矩阵4.四元数4.1四元数与欧拉角和旋转矩阵之间等效变换4.2测试Matlab代码5.总结1.简介常用姿态参数表达方式包括方向余弦矩阵、欧拉轴/角参数、欧拉角、四元数以及罗德里格参数等。高分辨率光学遥感卫星主要采用欧拉角与四元数对姿态参数进行描述。这里着重讲解欧拉角、旋转矩阵和四元数。2.欧拉角2.1欧拉角定义欧拉角是表征刚体旋转的一种方法之一,由莱昂哈德·欧拉引入的三个角度,用于描述刚体相对于固定坐标系的方向。在摄影测量、空间科学或其它技术领域,一般用一组(三个)欧拉角描述两个空间坐标之间的旋
我对新的Rails应用程序有一个有点奇怪的要求。我需要构建一个应用程序,其中所有路由都在多个命名空间中定义(让我解释一下)。我想要一个应用程序,其中学校科目(数学、英语等)是namespace:%w[mathenglish].eachdo|subject|namespacesubject.to_symdoresources:studentsendend这很棒而且有效,但它需要我为每个主题创建一个命名空间StudentsController,这意味着如果我添加一个新主题,那么我需要创建一个新Controller。我想创建一个Base::StudentsController,如果Math: