Я учусь создавать эффекты для wpf с помощью hlsl. В настоящее время я пытаюсь создать простой эффект, который отмечает края изображения. Я также хочу использовать для этого оператор Собеля, поэтому я установил общедоступный float2x3 в своем коде hlsl, но я не могу получить доступ к элементам в этой матрице.
Я пробовал вручную вводить правильные значения, и это работает, но не тогда, когда я использую цикл.
sampler2D imageSampler : register(s0);
float imageWidth : register(c0);
float imageHeight : register(c1);
float threshold : register(c2);
float2x3 op =
{
1.0f, 2.0f, 1.0f,
-1.0f, -2.0f, -1.0f
};
float grayScale(float3 color)
{
return (color.r + color.g + color.b) / 3;
}
float4 GetEdgeLoop(float2 coord, float2 pixelSize)
{
float2 current;
float avrg = 0;
float holder;
float gsHolder;
current.x = coord.x - pixelSize.x;
for (int x = 0; x < 2; x++)
{
current.y = coord.y - pixelSize.y;
for (int y = 0; y < 3; y++)
{
holder = op[x][y];
gsHolder = grayScale(tex2D(imageSampler, current).rgb);
avrg += gsHolder * holder;
current.y += pixelSize.y;
}
current.x += pixelSize.x * 2;
}
avrg = abs(avrg / 8);
if (avrg > threshold)
return float4(1, 0, 0, 1);
return tex2D(imageSampler, coord);
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 pixelSize = (1 / imageWidth, 1 / imageHeight);
return GetEdgeLoop(uv, pixelSize);
}
Этот метод должен возвращать красный цвет для достаточно сильных краев. Иногда это возвращает красный цвет, но явно не для краев.
У меня есть другой метод обнаружения краев, который действительно работает, но он выбирает нужные пиксели вручную:
float4 GetEdge(float2 coord, float2 pixelSize)
{
float avrg = 0;
avrg += grayScale(tex2D(imageSampler, float2(coord.x - pixelSize.x, coord.y - pixelSize.y)).rgb) * 1;
avrg += grayScale(tex2D(imageSampler, float2(coord.x - pixelSize.x, coord.y)).rgb) * 2;
avrg += grayScale(tex2D(imageSampler, float2(coord.x - pixelSize.x, coord.y + pixelSize.y)).rgb) * 1;
avrg += grayScale(tex2D(imageSampler, float2(coord.x + pixelSize.x, coord.y - pixelSize.y)).rgb) * (-1);
avrg += grayScale(tex2D(imageSampler, float2(coord.x + pixelSize.x, coord.y)).rgb) * (-2);
avrg += grayScale(tex2D(imageSampler, float2(coord.x + pixelSize.x, coord.y + pixelSize.y)).rgb) * (-1);
avrg = abs(avrg / 8);
if (avrg > threshold)
return float4(1, 0, 0, 1);
return tex2D(imageSampler, coord);
}
Этот метод не очень элегантный, и я хочу его заменить.