NDC 快速入门; 2. NDC 与 MDC 有何不同; 3. NDC 刨根问底 1. a)NDC 提供的 push 方法,可以将一个值放进容器中,理解成入栈操作,当然可以多放几个(自己试一试); d)通过 %X 获取 NDC 中所有的值; b)NDC 中的值是线程隔离的,互不影响; c) NDC 与 MDC 有何不同? a)MDC vs NDC ? b) MDC vs NDC ? NDC 提供的 pop 方法,可以将一个值从容器中拿出来,理解成出栈操作。 3. NDC 刨根问底 好奇是程序猿(媛)的通病,还是好奇的要看看 NDC 背后是什么? ? 见到源码,感觉累崩。
01 NDC和MDC的区别 Java中使用的日志的实现框架有很多种,常用的log4j和logback以及java.util.logging,而log4j是apache实现的一个开源日志组件(Wrapped 说完基本的日志框架的区别之后,我们再看看NDC和MDC。 不管是log4j还是logback,打印的日志要能体现出问题的所在,能够快速的定位到问题的症结,就必须携带上下文信息(context information),那么其存储该信息的两个重要的类就是NDC( NDC采用栈的机制存储上下文,线程独立的,子线程会从父线程拷贝上下文。 其调用方法如下: 1.开始调用 NDC.push(message); 2.删除栈顶消息 NDC.pop(); 3.清除全部的消息,必须在线程退出前显示的调用,否则会导致内存溢出。
然后,裁剪坐标系转换到标准设备坐标系(NDC)通过除以裁剪坐标系的w分量。 翻译: 视锥体裁剪剔除和标准化设备坐标(NDC) 在透视投影中,一个3D点是在一个截去上半部分的金字塔形状内(视图坐标系)被映射到一个立方体(NDC);x坐标的范围从[l,r]到[-1,1],y坐标的范围从 请注意:视图坐标系(相机坐标系或者眼睛坐标系)定义的是右手坐标系,但是NDC(标准设备坐标系)使用的是左手坐标系。 也就是说:在视图坐标系下:相机在原点处向负Z轴看去,而在NDC(标准设备坐标系)下沿着正Z轴看去。 翻译 正交体积和标准化设备坐标(NDC) 为正交投影构造投影矩阵比透视模式简单得多。 Xe,Ye和Ze在视图空间中的成分被线性映射到NDC。我们只需要将一个矩形体积缩放成一个立方体,然后将它移到原点。
NDC和MDCNDC(Nested Diagnostic Context)和MDC(Mapped Diagnostic Context)是log4j种非常有用的两个类,它们用于存储应用程序的上下文信息( NDC采用了一个类似栈的机制来push和pop上下文信息,每一个线程都独立地储存上下文信息。比如说一个servlet就可以针对每一个request创建对应的NDC,储存客户端地址等等信息。 MDC和NDC非常相似,所不同的是MDC内部使用了类似map的机制来存储信息,上下文信息也是每个线程独立地储存,所不同的是信息都是以它们的key值存储在”map”中。 NDC和MDC的原理是用了java的ThreadLocal类。可以针对不同线程存储信息。但是今天在log4j2上使用时发现没有找到NDC和MDC。查找官方文档,原来是换成了ThreadContext。
推导x,y坐标 向量投影到近平面,然后映射到NDC,就可以得到,在此不赘述。 整理式1.1,式1.2 式2.1 式2.2 整理后,式2.1、式2.2分母都有Ze,因此选择z'(NDC) = A*1/z(观察空间) + B,即可以和x,y的关系式对应起来,又满足我们的需求 (2019.08.15 补充:使用1/z还有一个重要的原因在于,光栅化时,需要进行透视校正插值,因为z'(NDC)与1/z(观察空间)是线性关系(证明:https://www.cnblogs.com/cys12345/archive /2009/03/16/1413821.html或《3D游戏与计算机图形学中的数学方法》 第3版,第5.4章节),所以z'(NDC) = A*1/z(观察空间) + B,另外,如果z'(NDC)直接保存为 观察空间) ,等到进行透视校正插值,再进行转换,这样做是不好的,因为透视校正插值是逐片元操作,就要重复非常多次的运算,直接保存为A*1/z(观察空间) + B,是逐顶点操作,运算次数就少很多) z'(NDC
4.4 NDC NDC是nested DiagnosticContext的缩写,意思是“嵌套的诊断上下文”。NDC是一种用来区分不同源码中交替出现的日志的手段。 NDC就是在这样的情况下发挥作用。注意NDC是以线程为基础的,每一个线程拥有一个NDC,每一个NDC的操作仅对运行该操作的线程有效。 注意它们都是静态函数: Push能够让当前线程进入一个NDC,假设该NDC不存在,则依据push的參数创建一个NDC并进入;假设再调用一次push,则进入子NDC; Pop能够让当前线程从上一级 argc,char** argv) { std::cout<< “1.empty NDC: ” <<NDC::get()<< std::endl; NDC::push(“context1”); std: : ” <<NDC::get()<< std::endl; NDC::push(“context3”); std::cout<< “4.push context3: ” <<NDC::get()<< std
6、NDC(nested DiagnosticContext)
嵌套的诊断上下文,A Nested Diagnostic Context, or NDC in short, is an instrument NDC就是在这种情况下发挥作用。注意NDC是以线程为基础的,每个线程拥有一个NDC,每个NDC的操作仅对执行该操作的线程有效。 and setMaxDepth affect the NDC of the current thread only. 下图指出了类中函数的调用关系:
常用的一些静态函数xxx()内部首先调用getNDC()函数得到一个NDC对象,之后继续调用对应的_xxx()虚函数。 例如:
void NDC::clear()
{
getNDC().
=soft.com.soft.com.log=soft.com.log=' $i; donefor i in `cat u.path` ; do sed -i -r -e 's=/log/zdr/(ndc -\w+-\w+).soft.com.log=/log/zdr/\1.log=' -e 's=/log/(ndc-\w+-\w+).soft.com.log=/log/\1.log=' $i; done 's/sganes,sganes/sganes/' {n,e}dc-emsts-app{1..4}.cfgsed -i 's=soft.com.soft.com.log=soft.com.log=' ndc-v5 -dalprs3.cfg sed -ri -e 's=/log/zdr/(ndc-\w+-\w+).soft.com.log=/log/zdr/\1.log=' -e 's=/log/(ndc-\w+ -\w+).soft.com.log=/log/\1.log=' ndc-v5-l2cacheprs8.cfgsed -r -e "s=(-p\s+'/opt/(\w+)/\S+)=\1 -u \2="
该矩阵将所有观察空间的顶点坐标变换到裁剪空间,接着,将变换后的顶点坐标(即裁剪坐标)的每个分量(x,y,z,w)(x,y,z,w)(x,y,z,w)除以坐标的 www 分量,使其变换为标准化设备坐标(NDC 这里我们需要注意的一点就是 : GL_PROJECTION 矩阵同时整合了裁剪(视锥体剔除)和标准化设备坐标(NDC)变换的功能(译注:这里不是指 GL_PROJECTION 矩阵本身整合了这些功能,而是指 透视投影 在透视投影中,视锥体(观察空间)中的一个3D坐标点会被映射到一个立方体中(NDC);其中 xxx 坐标范围会从 [l,r][l, r][l,r] 映射到 [−1,1][-1, 1][−1,1] 这里需要注意的是,观察空间是在右手坐标系下(OpenGL 使用右手坐标系)定义的,但是 NDC 却是在左手坐标系下定义的.换句话说就是,观察空间中的摄像机是指向 -Z 轴的,但是在 NDC 中,摄像机指向的却是 所有观察空间的 xex_exe, yey_eye 和 zez_eze 分量都被线性的映射到 NDC 中,我们要做的就是将长方体(观察空间)缩放成一个立方体(NDC),然后将其移动到原点位置.我们马上来算一下
而同样我们知道了,NDC的空间中的六个面的方程了,那么则存在如下的关系: M矩阵的逆矩阵的转置矩阵,变换透视空间的平面,就等于了NDC空间的平面方程了。 等式如下: M逆再转置*透视空间平面=NDC空间的平面 所以透视空间的平面等于如下: 透视空间平面=(M逆再转置再逆)NDC空间的平面 也就是: 透视空间平面=M转置NDC空间的平面 所以:
推导过程如下: 先由深度纹理逆推出NDC(归一化的设备坐标)下的顶点坐标,利用VP矩阵(视角*投影矩阵)的逆矩阵反向变换出每个像素在世界空间中的位置, 再利用世界空间下的坐标与前一帧的VP矩阵顺向变换出前一帧的 NDC坐标,利用NDC下前一帧和相当帧的坐标差来确定速度的方向, 最后利用速度的方向对纹理采样的结果进行加权平均并多次绘制,以达到带有物体运动方向的模糊效果。 基于这一原理,需要准备的要素有: 1.摄像机的深度纹理(是由NDC下的坐标映射来的,需要先反向映射回NDC) 2.当前帧的VP矩阵的逆矩阵 3.前一帧的VP矩阵 摄像机深度值和深度纹理的获取方法在之前的博客中有写 float d=SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv.zw); 60 //反映射回NDC CurViewInserseMatrix,H); 64 float4 worldPos=D/D.w; 65 66 //分别得到前一帧和当前帧的NDC
我们可以不太严谨地暂且认为,相机坐标经过了一个投影变换,就直接得到NDC了。NDC是什么呢?它才是真正的由OpenGL ES来定义的坐标。在NDC的定义中,x、y、z各个坐标都在[-1,1]之间。 因此,NDC定义了一个边长为2的立方体,每个边从-1到1,NDC中的每个坐标都位于这个立方体内(落在立方体外的顶点在前一步已经被裁剪掉了)。 值得注意的是,虽然NDC包含x、y、z三个坐标轴,但它主要表达了顶点在xOy平面内的位置,x和y坐标它们最终会对应到屏幕的像素位置上去。 这样NDC坐标就需要一个变换,才能变换到屏幕坐标,这个变换被称为视口变换。在OpenGL ES中,这个变换也是自动完成的,但需要我们通过glViewport接口来指定绘制屏幕的大小。 这里的视口变换是从NDC坐标变换到屏幕坐标,还没有到最终的像素位置。再从屏幕坐标对应到像素位置,是后面的光栅化完成的。
一个模型的局部坐标点经过MVP矩阵变换之后得到的是齐次空间坐标的点,而不是NDC坐标的点。 NDC坐标的点要经过透视除法才能得到,NDC的坐标的点在OpenGL中xyz都被映射到[-1,1]之间,而DX中xy被映射到[-1,1]之间,而z被映射到[0,1]之间。 如下图: 于是乎,我们的只要将视锥体空间中的点P的x坐标带入上面的公式,就能得到NDC空间的x’‘了。 +n)/(f-n) q =-2nf/(f-n) 于是zz’’=(f+n)z/(f-n)-2nf/(f-n) 我们将其转换为矩阵的形式: ok,经过上的讨论之后,我们知道了,什么是齐次坐标,什么是ndc 还需要知道的是,摄像机渲染的深度图,得到的是什么,是[0,1]范围的线性深度,还是[-1,1]的ndc中的非线性坐标呢? 答案是后者。
NDC是左手坐标系,而之前的坐标系都是右手坐标系。 屏幕空间 屏幕空间即glViewport函数定义的视口,它的取值范围由视口大小决定。 透视投影视锥与NDC空间(图源Reference) 从图中我们可以看到,我们的目的实际上就是将左侧的视锥映射到右侧的NDC空间中。 还需要注意一点,NDC实际上是左手坐标系,而之前的空间都是右手坐标系,因此我们还需要在投影过程中翻转z轴。 在齐次坐标转化为NDC坐标时,我们进行如下操作: 这样,我们就可以令 来引入这一项。 之后我们继续变换投影后的坐标 ,使 和 满足NDC坐标的约束。 首先计算z_{ndc}。
0 1 ] 简化后核心作用: 将 X 轴坐标 [0, windowWidth] 映射到标准化设备坐标(NDC )的 [-1, 1] 将 Y 轴坐标 [0, windowHeight] 映射到标准化设备坐标(NDC)的 [1, -1](实现 Y 轴翻转) Z 轴坐标 [0] 映射到 NDC 的 [0](二维场景无需深度变化
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
Conn nc *nats.Conn // gRPC Service Registrar nrpc *nrpc.Server // Service discovery client ndc *ndc.Client nodeLock sync.RWMutex //neighbor nodes neighborNodes map[string]discovery.Node i.Node.ServiceRegistrar(), i.s) go func() { err := i.Node.KeepAlive(node) return n.ndc.KeepAlive go func() { err := i.Node.Watch(proto.ServiceALL) resp, err := n.ndc.Get range resp.Nodes { n.handleNeighborNodes(discovery.NodeUp, &node) } return n.ndc.Watch
ModelState.IsValid) { vm.DoReInit(); return PartialView(vm); } else { //我这代码直接写这了 生成租户库和基本信息 随便写了下简单的系统表数据 var NDC }; var userrole = new FrameworkUserRole { UserCode = vm.Entity.Account, RoleCode = role.RoleCode }; NDC.Set <FrameworkUser>().Add(user); NDC.Set<FrameworkRole>().Add(role); NDC.Set<FrameworkUserRole>().Add(userrole 后期自己添加租户角色表吧 NDC.Set<FrameworkMenu>().AddRange(DC.Set<FrameworkMenu>().CheckContain(pr.Select(x => x.MenuItemId ).ToList(), x => x.ID).ToList()); NDC.Set<FunctionPrivilege>().AddRange(pr); NDC.SaveChanges(); //云解析
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
mediaid=MzI2ODc4NDc2NF8yMjQ3NTMzNjg1 https://res.wx.qq.com/voice/getvoice? mediaid=MzI2ODc4NDc2NF8yMjQ3NTMzNjg3 https://res.wx.qq.com/voice/getvoice? mediaid=MzI2ODc4NDc2NF8yMjQ3NTMzNjkx 只有最后一串字符不一样,查找这串字符: 可以看到在这个标签中出现: <mp-common-mpaudio class="js_editor_audio data-pluginname="insertaudio" data-trans_state="1" data-verify_state="3" voice_encode_fileid="MzI2ODc4<em>NDc</em>2NF8yMjQ3NTMzNjg1