为什么在2D渲染时primitive的位置需要偏移0.5,但3D渲染时不用

为什么在2D渲染时primitive的位置需要偏移0.5,但3D渲染时不用 

[复制链接]
  
电梯直达 跳转到指定楼层
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  分享分享
 
  
2#
  发表于 2010-5-3 13:39:09  |  只看该作者
本帖最后由 sssa2000 于 2010-5-3 13:56 编辑

这个问题属于光栅化时的填充规则的问题,
dx使用的填充规则是左上填充,
这应该是一个标准的填充规则,
在光栅化的时候 已经自动处理了这一过程。
 
 
  
3#
  发表于 2010-5-3 15:10:52  |  只看该作者
因为3D时你一般不可能把纹理像素和屏幕像素对齐,所以不会有看得出来的模糊问题。
导致需要这0.5像素偏移的原因是:在D3D9里,屏幕上方形像素的中心点是整数坐标,而对于纹理坐标则是像素左上角,两个坐标系的定义不一样,这个不一致造成了这个问题。

D3D10已经做出修改,全都以方形像素左上角为整数坐标点,两个坐标系定义一致了,也就不需要这个0.5的修正了。
 
 
  
4#
  发表于 2010-5-20 10:06:18  |  只看该作者
这个问题如上所说是光栅化规则决定的。
更实际地说,是和光栅化规则与纹理寻址规则的差别导致的——纹理uv的0,0是左上texel的左上角。
因此要想让texel->pixel准确对应(2D中常用),就需要对uv或pos之一做出调整。
当然,用PointFilter可以规避一定问题。
但是,更规范彻底的方式还是偏移quad的position,因为如果不做这种调整,在MSAA打开的情况下,会出现quad边缘的缝隙。
 
 
  
5#
  发表于 2010-6-12 20:23:03  |  只看该作者
2D的没有经过3D管线,给出的坐标直接是屏幕坐标,但是纹理是映射到2个三角形上的,顶点坐标和纹理坐标没有对齐,所以需要手工对齐。
3D的经过了3D管线,光栅化阶段已经对齐了,api帮你做好了,所以不需要你手工去做了。
要完全理解,必须自己把透视修正纹理映射实现一遍,你就懂了。
 
 
  
6#
  发表于 2010-6-13 15:21:39  |  只看该作者
学习了,细节决定成败
 
 
  
7#
  发表于 2010-11-24 17:39:02  |  只看该作者
2D偏移0.5是因为要图片的像素对应到屏幕屏幕像素的中心点位置,因此需要加0.5。
3D在光栅化的时候计算出来的uv值就是屏幕像素中心点的值,不用在后面加0.5的偏移。
2D和3D绘制像素的原理一样,方式不一样而已。
 
 
  
8#
  发表于 2011-6-17 22:31:39  |  只看该作者
我有个问题,我们做一个2D游戏用的HGE,它是3D加速的2D引擎,顶点也是经过了3D管线的。
但是在用Spirte画大图的时候,会出现没对齐导致模糊的情况,手动偏移纹理坐标0.5后,恢复正常。这是怎么回事呢
 
 
  
9#
  发表于 2011-6-27 17:46:09  |  只看该作者
这好像是dx9特有的吧
 
 
  
10#
  发表于 2011-7-19 23:36:50  |  只看该作者
好象都没有一个是全部回答对的.

要回答0.5 的问题, 首先要理解, 像素在坐标里面是如何来表达的?

一个像素在屏幕上是一个点?  还是一个方块?   800*600的屏幕,像素(2.3, 4.6) 是在屏幕的哪个位置?

 
 
  
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工程师来看,是左上角,对硬件来说,还是中心点。当然,实现方法有很多种。
 
 
  
12#
  发表于 2011-7-20 11:46:39  |  只看该作者
大牛,解释的清楚呀.
 
 
  
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老大帮忙解答下.
 
 
  
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来乘,最后一步才除,这样几乎没有误差,显示出来的就是点对点。
 
 
  
16#
  发表于 2013-11-2 22:59:50  |  只看该作者
lidudu 发表于 2010-5-3 15:10 
因为3D时你一般不可能把纹理像素和屏幕像素对齐,所以不会有看得出来的模糊问题。
导致需要这0.5像素偏移的 ...

学习了,原来DX11的UV坐标跟像素坐标统一了啊....这是10年的回复...以前没看到...
感谢分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Cesium中,要实现实渲染,你可以使用`Cesium.Primitive`对象和自定义的渲染函数来更新渲染的几何体或实体。 以下是一个简单的示例,展示如何使用`Cesium.Primitive`来实现实渲染: ```javascript // 创建一个自定义的Primitive var customPrimitive = new Cesium.Primitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.PrimitiveGeometry({ // 这里可以指定你的几何体类型和属性 // 例如: new Cesium.RectangleGeometry({ ... }) }), attributes: { // 这里可以设置几何体的属性 // 例如: color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED) } }), appearance: new Cesium.MaterialAppearance({ // 这里可以设置材质外观 // 例如: material: new Cesium.Material({ ... }) }) }); // 添加自定义Primitive到场景中 viewer.scene.primitives.add(customPrimitive); // 定义一个更新函数,用于实更新几何体或属性 function updateCustomPrimitive() { // 更新几何体的属性 // 例如: customPrimitive.geometryInstances.attributes.color = ...; // 刷新场景 viewer.scene.requestRender(); // 循环调用更新函数实现实渲染 requestAnimationFrame(updateCustomPrimitive); } // 启动实渲染 updateCustomPrimitive(); ``` 在以上代码中,我们创建了一个自定义的`Cesium.Primitive`对象,并将其添加到场景中。然后,我们定义了一个更新函数`updateCustomPrimitive()`,在该函数中可以更新几何体的属性,并使用`viewer.scene.requestRender()`方法刷新场景。最后,我们通过`requestAnimationFrame()`函数循环调用更新函数,实现实渲染。 你可以根据自己的需求,根据几何体和属性的不同,自定义渲染函数以实现实渲染
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值