posts - 225, comments - 62, trackbacks - 0, articles - 0
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

为什么texture wrapping不工作?

Posted on 2011-04-18 23:29 魔のkyo 阅读(966) 评论(3)  编辑 收藏 引用 所属分类: Graphics
D3D里面有两个容易混淆的概念,环绕纹理寻址模式(wrap texture address mode)和纹理环绕(texture wrapping)。

环绕纹理寻址模式,是一种纹理坐标寻址模式,指定了纹理坐标超出[0,1]的部分的处理方法,环绕纹理寻址模式就是简单的重复,如果用代码来描述它相当于对uv做了
u = fmod(u,1.0);
v = fmod(v,1.0);

纹理环绕,这个描述起来更麻烦些,它其实是改变了每个顶点的纹理坐标在光栅化时的插值方法。举个例子,如果有一个三角形的两个顶点u值分别等于0.9和0.1,在不启用纹理环绕时,他们之间的插值将在0,9~0.1上进行,而有的时候我们希望它在0.9~1.0连上0.0~0.1上进行,这时就可以通过指定WRAP_U实现。

环绕纹理寻址模式是默认的寻址模式,而纹理环绕默认是不启用的。

今天我做了个例子,在例子中球面的纹理需要启用u方向上的纹理环绕,然而我发现它并不工作。


球面的纹理坐标是在VertexShader中通过球的顶点位置坐标计算出来的,计算方法如下
    const float HALF_PI = 3.1415926/2;
    Out.UV.x = atan2(In.Position.z,In.Position.x) /HALF_PI;
    Out.UV.y = In.Position.y;
事实上这是一个单位球,这个的计算使得 u∈[0,4), v∈[-1,1],然后利用了wrap寻址模式进行寻址。然而,在边界处左右的顶点的u值分别是3.x和0.x,我期望在启用纹理环绕的情况下可以在3.x~4.0连上0.0~0.x上插值,但事实情况似乎是在3.x~0.x上直接做了插值才导致了上面图中的问题。
解决方法是将Shader改为
    const float HALF_PI = 3.1415926/2;
    Out.UV.x = atan2(In.Position.z,In.Position.x) /HALF_PI;
    Out.UV.x = fmod(Out.UV.x, 1); //手动实现了wrap寻址模式
    Out.UV.y = In.Position.y;
让u在区间[0,1]上,这时纹理环绕就正常工作了。
我用颜色输出了uv,可以看到明显的1.0和0.0的边界,说明插值是按照我需要的wrapping方法,从贴图的结果也可以看到是正常的。


结论:纹理环绕要求纹理坐标在[0,1]范围才能正常工作。也可以认为wrap寻址和texture wrapping不能同时工作。

只有注册用户登录后才能发表评论。