I'm searching a way to implement a linear gradient shader that behaves as the linear gradient in Photoshop (only the vertical case is necessary). It will be applied to 2D sprites.
Currently I'm passing to the pixel shader these parameters:
- StartColor.
- EndColor.
- Offset: the gradient starting point.
- Length: the gradient length (the range inside where the colors will be interpolated).
- isFixed: a boolean parameter that indicates if the gradient must be influenced by the camera position or not.
Here a first attempt of the vertex shader and the pixel shader that I've implemented:
struct VsInput
{
float3 position : VES_POSITION;
float2 uv : VES_TEXCOORD0;
float4 color : VES_COLOR;
};
struct VsOutput
{
float4 position : HPOS;
float2 uv : TEXCOORD0;
float4 color : COLOR0;
float4 outPos : TEXCOORD1;
};
VsOutput main(VsInput input)
{
VsOutput vsOutput;
vsOutput.position = MUL(float4(input.position, 1.0f), WorldViewProjection);
vsOutput.uv = input.uv;
vsOutput.color = input.color;
vsOutput.outPos = vsOutput.position;
return vsOutput;
}
struct PsInput
{
float4 Position : HPOS;
float2 UV : TEXCOORD0;
float4 Color : COLOR0;
float4 outPos : TEXCOORD1;
};
float4 startColor;
float4 endColor;
float offset;
float len;
bool isFixed;
float4 main(PsInput psInput) : COLOR
{
psInput.outPos = psInput.outPos / psInput.outPos.w;
float yScreenSize = 900.0f;
float yPixelCoordinate = 0.0f;
if (isFixed)
{
yPixelCoordinate = 0.5f * (1.0f - psInput.UV.y) * yScreenSize;
}
else
{
yPixelCoordinate = 0.5f * (psInput.outPos.y + 1.0f) * yScreenSize;
}
float gradient = (yPixelCoordinate + offset) / len;
gradient = clamp(gradient, 0.0f, 1.0f);
return lerp(startColor, endColor, gradient);
}