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