HLSL整数纹理坐标

时间:2018-12-03 09:47:03

标签: shader hlsl

我正在尝试在整数像素坐标之间进行插值,而不是在0-1之间进行插值,因为我使用的是点采样,因此我对像素分数不感兴趣,但是纹理坐标仍在像素着色器中即使数据类型为int2,也仍为float2。

pixelSize是1除以纹理大小

matrix WorldViewProjection;

float2 pixelSize;

Texture2D SpriteTexture;

sampler2D SpriteTextureSampler = sampler_state
{
    Texture = <SpriteTexture>;
    AddressU = clamp;
    AddressV = clamp;
    magfilter = POINT;
    minfilter = POINT;
    mipfilter = POINT;
};

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
    int2 TextureCoordinates : TEXCOORD0;
};

VertexShaderOutput SpriteVertexShader(float4 position : POSITION0, float4 color : COLOR0, float2 texCoord : TEXCOORD0)
{
    VertexShaderOutput output;
    output.Position = mul(position, WorldViewProjection);
    output.Color = color;
    output.TextureCoordinates = texCoord * (1 / pixelSize);
    return output;
}

float4 SpritePixelShader(VertexShaderOutput input) : COLOR
{
    float2 texCoords = input.TextureCoordinates * pixelSize;
    return tex2D(SpriteTextureSampler, texCoords) * input.Color;
}

technique SpriteDrawing
{
    pass P0
    {
        VertexShader = compile vs_2_0 SpriteVertexShader();
        PixelShader = compile ps_2_0 SpritePixelShader();
    }
};

1 个答案:

答案 0 :(得分:0)

我的理解是,您需要采用0-1范围并将其大小调整为0-w:h,然后再返回到0-1。一种非常有用的技术称为feature scaling

  

特征缩放是一种用于标准化自变量或数据特征范围的方法。在数据处理中,这也称为数据规范化,通常在数据预处理步骤中执行。

有几种解决方法,但我将重点介绍rescaling approach。最初,此方法着重于采用200-300之类的范围并将其缩放为0-1。数学很简单:

Rescaling

其中x是原始值,而x'是归一化值。


在我们的情况下,我们想朝相反的方向从0-1扩展到200-300,因此我们必须对其进行重做;但是当我们选择它时,为什么不把它放在可以满足您要求的任何方向:

customizable rescaling

将其转换为HLSL是一个简单的任务,我建议将其放入通用方法中以备后用:

float RescaleInRange(float value, float oldMin, float oldMax, float newMin, float newMax) {
    if (value < oldMin) value = oldMin;
    else if (value > oldMax) value = oldMax;
    return ((value - oldMin) / (oldMax - oldMin)) * (newMax - newMin) + newMin;
}

我会将您的TextureCoordinates保留为float2,以与大多数使用float2的行业标准保持一致。然后,在您的顶点着色器中,为其分配提供的texCoord。稍后,在像素着色器中,您可以使用上面提供的重新缩放来单独处理TextureCoordinates的单位(在下面的代码中称为UV

float w = textureSize.x;
float h = textureSize.y;
float x = RescaleInRange(UV.x, 0, 1, 0, w);
float y = RescaleInRange(UV.y, 0, 1, 0, h);
return tex2D(Sampler, float2(RescaleInRange(x, 0, w, 0, 1), RescaleInRange(y, 0, h, 0, 1))) * input.Color;