为什么在2D渲染时primitive的位置需要偏移0.5,但3D渲染时不用 [复制链接] increase8269 电梯直达 1# 发表于 2010-5-3 10:49:55 | 只看该作者 在 DirectX SDK document ("Mapping Texels to Pixels")中说在2D渲染时为将纹理像素值映射到屏幕中去,为了取得一对一的效果,primitive的位置需要偏移0.5,这个我看明白了,是因为sceen空间的(0,0)与primitive的(0,0)差(0.5,0.5),那么在3D渲染时,最终不也是要纹理映射,那也应该对primitive的位置进行0.5偏移啊,是不是Directx自动做了这一操作呢,想不明白,请教下各位。 分享到: 微信 收藏1 分享 回复 使用道具 举报 sssa2000 2# 发表于 2010-5-3 13:39:09 | 只看该作者 本帖最后由 sssa2000 于 2010-5-3 13:56 编辑这个问题属于光栅化时的填充规则的问题,dx使用的填充规则是左上填充,这应该是一个标准的填充规则,在光栅化的时候 已经自动处理了这一过程。 回复 支持 反对 使用道具 举报 lidudu 3# 发表于 2010-5-3 15:10:52 | 只看该作者 因为3D时你一般不可能把纹理像素和屏幕像素对齐,所以不会有看得出来的模糊问题。导致需要这0.5像素偏移的原因是:在D3D9里,屏幕上方形像素的中心点是整数坐标,而对于纹理坐标则是像素左上角,两个坐标系的定义不一样,这个不一致造成了这个问题。D3D10已经做出修改,全都以方形像素左上角为整数坐标点,两个坐标系定义一致了,也就不需要这个0.5的修正了。 回复 支持 反对 使用道具 举报 hourousha 4# 发表于 2010-5-20 10:06:18 | 只看该作者 这个问题如上所说是光栅化规则决定的。更实际地说,是和光栅化规则与纹理寻址规则的差别导致的——纹理uv的0,0是左上texel的左上角。因此要想让texel->pixel准确对应(2D中常用),就需要对uv或pos之一做出调整。当然,用PointFilter可以规避一定问题。但是,更规范彻底的方式还是偏移quad的position,因为如果不做这种调整,在MSAA打开的情况下,会出现quad边缘的缝隙。 回复 支持 反对 使用道具 举报 songge09 5# 发表于 2010-6-12 20:23:03 | 只看该作者 2D的没有经过3D管线,给出的坐标直接是屏幕坐标,但是纹理是映射到2个三角形上的,顶点坐标和纹理坐标没有对齐,所以需要手工对齐。3D的经过了3D管线,光栅化阶段已经对齐了,api帮你做好了,所以不需要你手工去做了。要完全理解,必须自己把透视修正纹理映射实现一遍,你就懂了。 回复 支持 反对 使用道具 举报 一笑而过 6# 发表于 2010-6-13 15:21:39 | 只看该作者 学习了,细节决定成败 回复 支持 反对 使用道具 举报 marly 7# 发表于 2010-11-24 17:39:02 | 只看该作者 2D偏移0.5是因为要图片的像素对应到屏幕屏幕像素的中心点位置,因此需要加0.5。3D在光栅化的时候计算出来的uv值就是屏幕像素中心点的值,不用在后面加0.5的偏移。2D和3D绘制像素的原理一样,方式不一样而已。 回复 支持 反对 使用道具 举报 mage1989 8# 发表于 2011-6-17 22:31:39 | 只看该作者 我有个问题,我们做一个2D游戏用的HGE,它是3D加速的2D引擎,顶点也是经过了3D管线的。但是在用Spirte画大图的时候,会出现没对齐导致模糊的情况,手动偏移纹理坐标0.5后,恢复正常。这是怎么回事呢 回复 支持 反对 使用道具 举报 rickerlian 9# 发表于 2011-6-27 17:46:09 | 只看该作者 这好像是dx9特有的吧 回复 支持 反对 使用道具 举报 marshell 10# 发表于 2011-7-19 23:36:50 | 只看该作者 好象都没有一个是全部回答对的.要回答0.5 的问题, 首先要理解, 像素在坐标里面是如何来表达的?一个像素在屏幕上是一个点? 还是一个方块? 800*600的屏幕,像素(2.3, 4.6) 是在屏幕的哪个位置? 回复 支持 反对 使用道具 举报 ic.expert 11# 发表于 2011-7-20 00:01:45 | 只看该作者 回复 lidudu 的帖子如果从DX9变换到DX10,那么做对3D 流水线中Clipping单元的要求应该就会改变比如原来一个1024x768对Clipping的要求是可能是min(0 , 0 ) max (1024 , 768)切割(SCS坐标系) ,即,对每个像素中心点采样,像素地址= 像素ID+0.5 。 那么现在要对左上角采样,那么Clipper就需要改成对(-0.5 , -0.5) (1023.5, 767.5) 切割(SCS坐标系),然后我们可以很容易的吧“左上角”的点当做采样点。这样,对SW工程师来看,是左上角,对硬件来说,还是中心点。当然,实现方法有很多种。 回复 支持 反对 使用道具 举报 marshell 12# 发表于 2011-7-20 11:46:39 | 只看该作者 大牛,解释的清楚呀. 回复 支持 反对 使用道具 举报 tgame 13# 发表于 2011-7-25 23:21:51 | 只看该作者 回复 ic.expert 的帖子void VS_ScreenQuad(float4 posOSITION ,float2 tex0:TEXCOORD0 ,out float2 oTex0 :TEXCOORD0 ,out float4 oColor:COLOR ,out float4 oPos : POSITION){ oPos = float4(sign(pos.xz), 0, 1); oColor = float4(1.0,1.0,1.0,1.0); oTex0 = (float2(oPos.x, -oPos.y) + 1.0f) * 0.5f;}D3D9的情况下,Linear采样,这样输出,为什么同样大小的ScreenQuad和贴图会模糊?IC老大帮忙解答下. 回复 支持 反对 使用道具 举报 liumazi 14# 发表于 2013-10-14 22:14:34 | 只看该作者 OpenGL 存在这个问题吗 回复 支持 反对 使用道具 举报 泉映静月 15# 发表于 2013-11-2 20:21:58 | 只看该作者 楼上说3D会自动对齐是可能不太准确。3D渲染时,因为本身不精确,都是浮点运算,使用是自己的3D坐标系,然后投影到屏幕坐标上,0.5像素的偏移一般没有意义。但3D本身不会自动偏移0.5像素。如果你要在透视投影下实现2D点对点显示,也就是把一个图片精确显示出来,同样需要偏移0.5像素,不过这个0.5像素是要经过各矩阵转换的,要计算好,最起码透视矩阵少不了。我亲自测试过,没有直接使用矩阵反向计算,而是使用中学的几何知识,先做整数乘,0.5也是按1来乘,最后一步才除,这样几乎没有误差,显示出来的就是点对点。 回复 支持 反对 使用道具 举报 crazii 16# 发表于 2013-11-2 22:59:50 | 只看该作者 lidudu 发表于 2010-5-3 15:10 因为3D时你一般不可能把纹理像素和屏幕像素对齐,所以不会有看得出来的模糊问题。 导致需要这0.5像素偏移的 ... 学习了,原来DX11的UV坐标跟像素坐标统一了啊....这是10年的回复...以前没看到...感谢分享