如何创建对角HLSL过渡着色器

时间:2016-01-03 05:22:14

标签: wpf hlsl pixel-shader

我正在尝试调整Codeplex上WPF像素着色器效果库中的几个HLSL着色器的代码,以创建一个像素着色器,通过在Texture1上滑动Texture2来创建从Texture1到Texture2的对角线过渡,就好像它是覆盖的一样(即Texture1保持“静止”,而Texture2逐渐从左上角替换Texture1)。

我正在努力正确理解“uv”符号以及如何操纵它来实现我的目标。

到目前为止,我已经尝试了

float Progress : register(C0);

sampler2D Texture1 : register(s0);
sampler2D Texture2 : register(s1);

struct VS_OUTPUT
{
    float4 Position  : POSITION;
    float4 Color     : COlOR;
    float2 UV        : TEXCOORD;
};

float4 SampleWithBorder(float4 border, sampler2D tex, float2 uv)
{
    if (any(saturate(uv) - uv))
{
    return border;
}
else
{
    return tex2D(tex, uv);
}
}

float4 SlideDiagonal(float2 uv,float progress)
{
  uv += progress;

  float4 c1 = SampleWithBorder(float4(0,0,0,0), Texture2, uv);

  if(c1.a <=0)
  {
        return tex2D(Texture1, uv);
  }

  return c1;
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 main(VS_OUTPUT input) : COlOR
{
  return SlideDiagonal(input.UV, Progress/100);
}

以及

float Progress : register(C0);

sampler2D Texture1 : register(s1);
sampler2D Texture2 : register(s0);


float4 SampleWithBorder(float4 border, sampler2D tex, float2 uv)
{
if (any(saturate(uv) - uv))
{
    return border;
}
else
{
    return tex2D(tex, uv);
}
}

float4 Shrink(float2 uv,float progress)
{
float speed = 200;
float2 center = float2(0.001, 0.001);
float2 toUV = uv - center;
float distanceFromCenter = length(toUV);
float2 normToUV = toUV / distanceFromCenter;

float2 newUV = center + normToUV * (distanceFromCenter *(progress*speed+1));

float4 c1 = SampleWithBorder(float4(0,0,0,0), Texture2, newUV); 

if(c1.a <= 0)
{
    return tex2D(Texture1, uv);
}

return c1;

}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 main(float2 uv : TEXCOORD) : COlOR
{
return Shrink(uv, Progress/100);
}

但在两种情况下,“幻灯片”反向运行,随着进度增加到1,减少可见Texture2的数量,在前者的情况下,Texture1根本不显示。

我在圣诞节期间几次回到这个问题无济于事,现在我觉得我正在遭遇“树木问题”。

如果有人知道这个特定问题的解决方案,我们将不胜感激。

本着“教人钓鱼”的精神,如果有任何信息可以帮助我理解如何操纵“uv”,那也很棒。

非常感谢您的帮助 问候 伊恩卡森

2 个答案:

答案 0 :(得分:1)

纹理坐标(uv)指定在哪里查看纹理。用线

uv += progress;

根据进度移动纹理坐标。如果为零,则使用原始坐标(并显示整个Texture2)。通过增加progress,您会越来越多地到Texture2的右下角并将其绘制在原始位置。这样可以让纹理滑向左上角。所以,如果您想要反过来,请尝试:

uv += 1 - progress;

答案 1 :(得分:0)

非常感谢Nico在树上建立空地!他的回答让我改变了解决这个问题所需要的观点。 @Nico - Upvote for you,谢谢你的伴侣。

为了完整性,我已经包含了我的Shazzam小叮当的最终结果,它允许使用称为(富有想象力)&#34;角落&#34;的浮动输入从4个角中的任意角落进行对角滑动。在生产中,浮点数将被一个由可能的角点枚举驱动的int替换--TopLeft,TopRight,BottomRight,BottomLeft。代码中的顺序如图所示,由1,2,3和1表示。 4。

以下是着色器:

/// <summary>Modifies the Progress value.</summary> 
/// <minValue>0</minValue>
/// <maxValue>100</maxValue>
/// <defaultValue>0</defaultValue>
float Progress : register(C0);

/// <summary>Modifies the Corner value.</summary> 
/// <minValue>1</minValue>
/// <maxValue>1</maxValue>
/// <defaultValue>1</defaultValue>
float Corner : register(C1);

sampler2D Texture1 : register(s0);
sampler2D Texture2 : register(s1);

float4 SampleWithBorder(float4 border, sampler2D tex, float2 uv, float corner)
{
    if (any(saturate(uv) - uv))
    {
        return border;
    }
    else
    {
        float2 rev = uv;

        //Swap y position again to counteract the inversion caused by 
        //needing to get to get to corners BottomLeft and TopRight
        if(corner >=2 && corner < 3 || corner>=4
        {
            rev.y = 1 - rev.y;
        }

        return tex2D(tex, rev);
    }
}

float4 SlideDiagonal(float2 uv, float progress, float corner)
{
  float2 rev = uv;

  //Swap y position to get to corners BottomLeft and TopRight
  if(corner >=2 && corner < 3 || corner>=4)
  {
      rev.y = 1 - rev.y;
  }

  float2 newUV;

  //TopLeft
  if(corner >= 1 && corner < 2)
  {
      newUV = rev + (1- progress);
  }

  //TopRight
  if(corner >= 2 && corner < 3)
  {
      newUV = rev - (1- progress);
  }

  //BottomRight
  if(corner >= 3 && corner < 4)
  {
      newUV = rev - (1- progress);
  }

  //BottomLeft
  if(corner >= 4)
  {
      newUV = rev + (1- progress);
  }


  float4 c1 = SampleWithBorder(float4(0,0,0,0), Texture2, newUV, corner);

  if(c1.a <=0)
  {
      return tex2D(Texture1, uv);
  }

  return c1;
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 main(float2 input : TEXCOORD) : COlOR
{
  return SlideDiagonal(input, Progress/100, Corner);
}