HLSL和DX Skybox问题(创建接缝)

时间:2012-05-05 10:40:25

标签: c++ directx direct3d hlsl

我(重新)学习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();
    }
}

3 个答案:

答案 0 :(得分:1)

您需要使用setsampler状态来夹住纹理坐标以消除接缝。这个toymaker页面解释了这一点。 Toymaker是一个学习Direct3D的好网站,如果你有任何问题,你应该查看教程。

答案 1 :(得分: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);

不用担心任何接缝! :)

答案 2 :(得分:1)

为避免接缝,您需要在单个DrawIndexedPrimitive调用中绘制天空盒,最好使用三角形条。不要将每个面部绘制为单独的基元或单个矩阵转换的单独基元 - 您将获得接缝。如果由于某些无法解释的原因不希望对天空盒部件使用单个DrawIndexedPrimitive调用,则必须确保使用相同的矩阵(每个调用中使用的相同的世界+视图+投影矩阵)和角的相同坐标值绘制所有面顶点 - 即“顶部”面应该对“侧面”使用的角使用完全相同的矢量(位置)。

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

  1. 立方体贴图(看起来就像你正在做的那样) - 为天空盒制作8个顶点,将它们绘制为索引基元。
  2. 或者填充未使用区域的未打包“atlas”纹理。边框颜色。
  3. 或者 - 如果你对着色器很好,你可以使用着色器“光线追踪”天空盒。