HLSL Integer Texture Coordinates

北城以北 提交于 2020-01-16 00:44:46

问题


I'm trying to interpolate between integer pixel coordinates instead of between 0-1, because I'm using point sampling, so I'm not interested in fractions of pixels, but the texture coordinates are still coming into the pixel shader as float2 even though the data type is int2.

pixelSize is 1 divided by texture size

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:


My understanding is that you need to take a range of 0-1 and resize it to 0-w:h then back to 0-1 later. A very useful technique for this is called feature scaling:

Feature scaling is a method used to standardize the range of independent variables or features of data. In data processing, it is also known as data normalization and is generally performed during the data preprocessing step.

There are several approaches to this, but I will focus on the rescaling approach. Originally this approach focuses on taking a range such as 200-300 and scaling it to 0-1. The math is simply:

Where x is the original value and x' is the normalized value.


In our case we want to go the opposite direction and scale from 0-1 back to 200-300 so we have to rework it; but while we're at it why not make it where we can go either direction to meet your requirements:

Translating this into HLSL is a simple task and I would recommend putting it in a common method for reuse later:

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

I would leave your TextureCoordinates as a float2 to remain consistent with industry standards where most use float2 for this. Then in your vertex shader just assign it the texCoord that was supplied. Later, in your pixel shader you can use the rescale supplied above to work the units of TextureCoordinates individually (called UV in my code below):

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;


来源:https://stackoverflow.com/questions/53591092/hlsl-integer-texture-coordinates

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!