1

three.js 3d 库中有一个方便的功能,您可以将采样器设置为重复模式并将重复属性设置为您喜欢的一些值,例如,(3, 5) 表示此纹理将水平重复 3 次和 5 次垂直。但是现在我正在使用 DirectX,我找不到一些好的解决方案来解决这个问题。请注意,顶点的 UV 坐标仍然介于 0 到 1 之间,我不想更改我的 HLSL 代码,因为我想要一个可编程的解决方案,非常感谢!

编辑:假设我已经有一个立方体模型。并且其顶点的纹理坐标介于 0 和 1 之间。如果我使用环绕模式或钳位模式对纹理进行采样,现在一切正常。但我想在它的一个面上重复纹理,我首先需要更改为环绕模式。这是我已经知道的。然后我必须编辑我的模型,使纹理坐标范围为 0-3。如果我不改变我的模型怎么办?到目前为止,我得出了一种方法:我需要向像素着色器添加一个变量,表示地图重复了多少次,并且在采样时我将乘以这个因子来协调。我认为这不是一个优雅的解决方案 emmmm...</p>

4

2 回答 2

2

由于您已经编辑了问题,因此您的问题还有另一个答案:

据我了解,你有一张这样的 uv 脸:

0,1         1,1
 -------------
 |           |
 |           |
 |           |
 -------------
0,0         1,0

但是希望纹理重复 3 次(例如)而不是 1 次。(不改变原模型)

这里有多种解决方案:

您可以在更新缓冲区时执行此操作(如果您这样做):

    D3D11_MAPPED_SUBRESOURCE resource;

    HRESULT hResult = D3DDeviceContext->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
    if(hResult != S_OK) return false;

    YourVertexFormat *ptr=(YourVertexFormat*)resource.pData;
    for(int i=0;i<vertexCount;i++)
    {
        ptr[i] = vertices[i];
        ptr[i].uv.x *= multiplyX; //in your case 3
        ptr[i].uv.y *= multiplyY; //in your case 5 
    }
    D3DDeviceContext->Unmap(vertexBuffer, 0);

但是,如果您无论如何都不需要更新缓冲区,我不会推荐它,因为它非常慢。

更快的方法是使用顶点着色器:

cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION0;
    float2 uv : TEXCOORD0;
    // ...
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 uv : TEXCOORD0;
    // ...
};

PixelInputType main(VertexInputType input)
{
    input.position.w = 1.0f;

    PixelInputType output;
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);

    This is what you basicly need:
    output.uv = input.uv * 3; // 3x3

    Or more advanced:
    output.uv = float2(input.u * 3, input.v * 5);

    // ...

    return output;
}

我会推荐顶点着色器解决方案,因为它速度很快,而且在 Directx 中你无论如何都使用顶点着色器,所以它不像缓冲区更新解决方案那样昂贵......

希望这有助于解决您的问题:)

于 2013-07-20T01:20:39.470 回答
1

你基本上想像这样创建一个采样器状态:

ID3D11SamplerState* m_sampleState;
3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

// Create the texture sampler state.
result = ifDEVICE->ifDX11->getD3DDevice()->CreateSamplerState(&samplerDesc, &m_sampleState);

当你设置你的着色器常量时,调用这个:

ifDEVICE->ifDX11->getD3DDeviceContext()->PSSetSamplers(0, 1, &m_sampleState);

然后你可以像这样编写你的像素着色器:

Texture2D Texture;
SamplerState SampleType;

...

float4 main(PixelInputType input) : SV_TARGET
{
    float4 textureColor = shaderTexture.Sample(SampleType, input.uv);
    ...
}

希望有帮助...

于 2013-07-15T16:01:12.277 回答