Directx 如何在DX中重复纹理

Directx 如何在DX中重复纹理,directx,texture-mapping,Directx,Texture Mapping,three.js 3d库中有一个方便的功能,您可以将采样器设置为重复模式,并将“重复”属性设置为您喜欢的某些值,例如,(3,5)表示此纹理将在水平方向重复3次,在垂直方向重复5次。但是现在我正在使用DirectX,我找不到解决这个问题的好方法。请注意,顶点的UV坐标仍然在0到1之间,我不想更改我的HLSL代码,因为我需要一个可编程的解决方案,非常感谢 编辑:假设我已经有了一个立方体模型。其顶点的纹理坐标介于0和1之间。如果我使用包裹模式或钳制模式对纹理进行采样,现在一切都正常了。但是我想在它的一

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


编辑:假设我已经有了一个立方体模型。其顶点的纹理坐标介于0和1之间。如果我使用包裹模式或钳制模式对纹理进行采样,现在一切都正常了。但是我想在它的一个面上重复一个纹理,我首先需要更改为包裹模式。这是我已经知道的。然后我必须编辑我的模型,使纹理坐标范围为0-3。如果我不改变我的模型呢?到目前为止,我找到了一种方法:我需要向像素着色器添加一个变量,表示贴图重复了多少次,我将在采样时将该因子乘以坐标。我认为这不是一个优雅的解决方案,嗯…

您基本上希望创建一个采样器状态,如下所示:

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);
    ...
}

希望这对您有所帮助……

既然您已经编辑了您的问题,那么您的问题还有另一个答案:

据我所知,你的脸上有紫外线,就像这样:

0,1         1,1
 -------------
 |           |
 |           |
 |           |
 -------------
0,0         1,0
但是希望纹理重复3次(例如),而不是1次。 (不更改原始模型)

这里有多种解决方案:

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

我建议使用顶点着色器解决方案,因为它速度快,而且在directx中无论如何都可以使用顶点着色器,所以它没有缓冲区更新解决方案那么昂贵


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

在Direct3D 10/11中,您正在查找采样状态的
地址u
地址v
地址w
字段。当纹理坐标位于[0,1]范围之外时,它们控制如何处理纹理坐标。您可以将它们设置为
border
mirror
clamp
,也可以设置为
wrap
(重复)。谢谢,但请参考答案1查看我的评论。你的答案与CNG27的答案有些相似。谢谢!但这实际上对我的问题没有帮助…请注意,当UV纹理坐标在0-1之间时,我需要一个重复的纹理!!在你的代码中,一个人必须将坐标从0-1调整到0-3,这样他才能实现重复效果,现在对我来说似乎太贵了:-)@user2310794你说的昂贵是什么意思?无论如何,在运行时(在CPU上),将顶点的texcoords乘以重复率(在您的示例中为3和5),并使用包裹寻址模式采样器。但这显然比离线编辑模型要贵。是的,那正是我当时所做的。起初,我想要一个由库本身提供的功能,但很快我改变了主意。。。无论如何,谢谢你关注我的愚蠢问题!
    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;
}