Градиент
Градиент это плавно изменение цвета. Градиент имеет направление, он может быть вертикальным, горизонтальным, диагональным, или произвольным.
Для начала давайте попробуем залить весь экран один цветом без градиента. Для этого нужно пройтись по каждому пикселю и закрасить его.
Объект Graphics не имеет возможности закрашивать отдельные пиксели (можно использовать FillRectangle для каждого пикселя, но это очень не эффективно). Поэтому давайте создадим битмап, который позволяет задавать отдельные пиксели. Отрисуем сперва всю нашу сцену туда, а затем просто выведем его.
Создадим Bitmap с размерами равными размерам окна.
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
Paint += Form1_Paint;
bmp = new Bitmap(ClientSize.Width, ClientSize.Height);
Init(); // вызываем функцию создания bmp один раз
}
Bitmap bmp; // наша сцена
Воспользуемся функцией SetPixel чтобы рисовать отдельные пиксели
// функция инициализации сцены
// будет вызывать один из методов заполнения
void Init() {
Fill(Color.Orange);
}
// функция заполняющая Bitmap одним цветом
void Fill (Color color) {
for (int i = 0; i < ClientSize.Width; i++)
{
for (int j = 0; j < ClientSize.Height; j++)
{
bmp.SetPixel(i, j, color);
}
}
}
// функция отрисовки формы
private void Form1_Paint(object? sender, PaintEventArgs e)
{
e.Graphics.DrawImageUnscaled(bmp, 0, 0); // выводим bmp
}
Запустим:

Горизонтальный градиент
Теперь давайте сделаем горизонтальный градиент от черного до зеленого цвета. То есть слева нашего окна все линии будут черные и плавно по направлению к правому краю окна (в сторону увелечения X) цвет вертикальных линий должен становится все зеленее и зеленее пока не достигнет максимальной яркости (255) для самой правой линии окна.
Выведем градиент на экран, для этого нам необоходимо заполнить каждый пиксель окна плавно увеличивая интенсивность яроксти цвета слева направо.
void Init(){ // изменим содержимое функции Init
DrawHorizontalGradient();
}
// функция заливки горизонтального градиента
public void DrawHorizontalGradient()
{
for (int i = 0; i < ClientSize.Width; i++)
{
double koef = (i) / (double)ClientSize.Width;
Color color = Color.FromArgb((int)(koef * 255), 0, 0);
for (int j = 0; j < ClientSize.Height; j++)
{
bmp.SetPixel(i, j, color);
}
}
}
Получим такой результат:

Диагональный градиент
Теперь создадим новый метод диагонального градиента. Для этого нужно расчитывать цвет каждого пикселя перед выводом, потому что цвет становится функцией от двух координат сразу (x,y)
Максимальная яркость зеленого цвета будет в правой нижней точки окна (с максимальным X и максимальным Y)
public void Init() {
DrawDiagGradient();
}
public void DrawDiagGradient()
{
Bitmap bmp = new Bitmap(ClientSize.Width, ClientSize.Height);
for (int i = 0; i < ClientSize.Height; i++)
{
for (int j = 0; j < ClientSize.Width; j++)
{
double koef = (i + j) / (double)(ClientSize.Height + ClientSize.Width);
Color color = Color.FromArgb(0, (int)(koef * 255), 0);
bmp.SetPixel(j, i, color);
}
}
}Получим диагональный черно-зеленый градиент:

Упражнения:
1. Реализовать вертикальный градиент

2. Реализовать круговой градиент (из центра равномерно во все стороны)

3. Добавьте аргумент цвета в параметры каждой функции градиента, чтобы цвет не был статично задан (как сейчас) внутри функции, а мог передевать в функцию в момент вызова.
// измененная сигнатура метода должна выглядеть вот так:
public void DrawHorizontalGradient(Color color)