在three.js 3d库中有一个方便的功能,您可以将采样器设置为重复模式并将repeat属性设置为您喜欢的某些值,例如,(3,5)表示此纹理将水平重复3次和垂直5次。但现在我正在使用DirectX,我找不到一些解决这个问题的好方法。请注意,顶点的UV坐标仍然在0到1的范围内,我不想更改我的HLSL代码,因为我想要一个可编程的解决方案,非常感谢!
编辑:假设我已经有了一个立方体模型。并且其顶点的纹理坐标在0和1之间。如果我使用环绕模式或钳位模式对纹理进行采样,那么现在一切正常。但是我想在其中一个面上重复一个纹理,我首先需要改为换行模式。那是我已经知道了。然后我必须编辑我的模型,使纹理坐标范围为0-3。如果我不改变模型怎么办?到目前为止,我提出了一种方法:我需要在像素着色器中添加一个变量来表示地图重复的次数,我将在采样时将此因子乘以坐标。我觉得这不是一个优雅的解决方案......
答案 0 :(得分: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);
...
}
希望有帮助...
答案 1 :(得分:1)
由于您已编辑了问题,因此您的问题还有另一个答案:
根据我的理解,你有一张像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中你无论如何都使用顶点着色器,因此它不像缓冲区更新解决方案那么昂贵......
希望有助于解决您的问题:)