【问题标题】:HLSL and DX Skybox Issues (creates seams)HLSL 和 DX Skybox 问题(创建接缝)
【发布时间】:2012-05-05 10:40:24
【问题描述】:

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

【问题讨论】:

    标签: c++ directx direct3d hlsl


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我理解钳位的概念......并且如前所述,我对 HLSL 之外的这个天空盒没有任何问题......在四边形渲染后设置渲染状态非常有效。问题是我正在使用着色器,所以问题来自 .fx 文件。现在我已经为 tex 坐标使用了 CLAMP 参数,但它不起作用......包装(我在这里使用的东西)有效,但我得到了接缝。我假设它是因为我已经从四边形构建了盒子,但我在 HLSL 中使用了 texCUBE 函数。所以真正的麻烦是我应该改用什么? (假设我是对的)
      【解决方案3】:

      您可能希望仅使用一个四边形来绘制天空盒。您需要的一切都是 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);
      

      不用担心任何接缝! :)

      【讨论】:

      • 请记住,世界变换应该是到相机位置的平移。
      猜你喜欢
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多