问题描述
我正在尝试在整数像素坐标之间进行插值,而不是在0-1之间进行插值,因为我使用的是点采样,因此我对像素分数不感兴趣,但是纹理坐标仍在像素着色器中即使数据类型为int2,也仍为float2.
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是1除以纹理大小
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();
}
};
推荐答案
我的理解是,您需要将范围0-1
设置为0-w:h
,然后再重新设置为0-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:
有几种解决方法,但我将重点介绍重新缩放方法.最初,此方法着重于采用一个范围,例如200-300
并将其缩放为0-1
.数学很简单:
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:
其中x
是原始值,而x'
是归一化值.
Where x
is the original value and x'
is the normalized value.
在我们的情况下,我们想朝相反的方向从0-1
缩放到200-300
,因此我们必须对其进行重做.但是当我们选择它时,为什么不把它放在可以满足您要求的任一方向上即可:
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:
将其转换为HLSL
是一个简单的任务,我建议将其放入通用方法中以备后用:
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;
}
我会将您的TextureCoordinates
保留为float2
,以与大多数使用float2
的行业标准保持一致.然后在您的顶点着色器中,为其分配提供的texCoord
.稍后,在像素着色器中,您可以使用上面提供的重新缩放来分别处理TextureCoordinates
的单位(在下面的代码中称为UV
):
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;
这篇关于HLSL整数纹理坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!