2

我正在(重新)学习 DirectX 并已进入 HLSL 编码。在使用我的自定义 .fx 文件之前,我为带有四边形顶点缓冲区的游戏创建了一个天空盒。一切正常...纹理映射和精美包装。然而,现在我已经设置了 HLSL 来管理顶点,四边形相交的地方有独特的接缝。纹理都正确排列我只是无法摆脱这个该死的接缝!

我倾向于认为问题出在 texCube 上……或者更确切地说是这里的所有纹理信息。我正在 DX 中对四边形进行纹理处理……可能只是我仍然不太了解两者之间的联系……不确定。无论如何,提前感谢您的帮助!

这是 .fx 文件:

float4x4 World;
float4x4 View;
float4x4 Projection;

float3 CameraPosition;

Texture SkyBoxTexture; 

samplerCUBE SkyBoxSampler = sampler_state 
{ 
   texture = <SkyBoxTexture>; 
   minfilter = ANISOTROPIC; 
   mipfilter = LINEAR; 
   AddressU = Wrap; 
   AddressV = Wrap;
   AddressW = Wrap;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 TextureCoordinate : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    float4 VertexPosition = mul(input.Position, World);
    output.TextureCoordinate = VertexPosition - CameraPosition;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    return texCUBE(SkyBoxSampler, normalize(input.TextureCoordinate));
}

technique Skybox
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}
4

3 回答 3

1

您需要使用 setsampler 状态钳制纹理坐标以消除接缝。这个玩具制造商页面解释了这一点。Toymaker 是学习 Direct3D 的绝佳网站,如果您有任何问题,请查看教程。

于 2012-05-05T12:26:00.977 回答
1

您可能希望仅使用一个四边形来绘制天空盒。您需要的一切都是 World*View*Proj 矩阵的逆矩阵,即 (World*View*Proj)^(-1)。

四边形的顶点应该是:(1, 1, 1, 1), (1, -1, 1, 1), (-1, 1, 1, 1), (-1, -1, 1, 1 )。

然后在 VS 中计算纹理坐标:

float4 pos = mul(vPos, WorldViewProjMatrixInv);
float3 tex_coord = pos.xyz / pos.w;

最后在 PS 中对纹理进行采样:

float4 color = texCUBE(sampler, tex_coord);

不用担心任何接缝!:)

于 2012-05-08T19:34:29.157 回答
1

为了避免接缝,您需要在单个 DrawIndexedPrimitive 调用中绘制天空盒,最好使用三角形条。不要将每个面绘制为用单独的矩阵或类似的东西转换的单独的图元 - 你会得到接缝。如果您出于某种无法解释的原因不想对天空盒部件使用单个 DrawIndexedPrimitive 调用,那么您必须确保使用相同的矩阵(每次调用中使用相同的世界 + 视图 + 投影矩阵)和相同的角坐标值绘制所有面顶点 - 即“顶”面应该对“侧面”使用的角使用完全相同的向量(位置)。

另一件事是您应该将天空盒存储为

  1. 立方体贴图(看起来就是你正在做的) - 只为天空盒制作 8 个顶点,将它们绘制为索引图元。
  2. 或者一个未包装的“地图集”纹理,其中填充了未使用的区域。带边框颜色。

或者 - 如果你对着色器很好,你可以使用着色器“光线追踪”天空盒。

于 2012-05-08T21:08:16.033 回答