Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > Градиентная заливка треугольника.


Автор: nnvz 21.2.2006, 09:53
Задача состоит в следующем: имеем на полотне три виртуальных точки, каждая своего цвета. Нужно залить треугольник, образуемый этими точками, ровным градиентом, примерно так:

user posted image

Нужно реализовать это безо всяких сторонних библиотек вроде OpenGL.

Автор: maxim1000 21.2.2006, 11:33
а что именно интересует: вычисление цвета точки или способ рисования этих точек?

Автор: nnvz 21.2.2006, 11:53
Именно вычисление цвета, куда выводить и как - неважно

Автор: maxim1000 21.2.2006, 12:14
ну, из того, что я увидел, можно придумать такое:
1. проводим медиану из левой точки
2. верхний треугольник закрашиваем градиентом от верхней угловой точки до левой
3. нижний - от нижней до левой

еще можно немного другой способ, он более логичным кажется:
каждая точка в треугольнике представляется, как выпуклая комбинация его вершин
можно взять эти коэффициенты и составить по ним выпуклую комбинацию уже из цветов (для каждой точки нужно будет указать свой цвет)...

Автор: MBo 21.2.2006, 17:39
Даны три точки A,B,C. Введем непрямоугольную систему координат с началом в точке A и базовыми векторами i=(B-A) и j=(C-A).
Для точки D внутри треугольника найдем параметрические координаты s и t из векторного соотношения
D-A = s*i +t*j, расписав его по координатам X и Y.
Цвет в точке D будет линейной комбинацией цветов вершин с весами A (1-s-t) B(s) C(t)
s и t лежат в пределах 0..1, и их сумма не превышает 1. Например, середина стороны BC имеет координаты 1/2, 1/2 и цвет - среднее B и С
Пример на Дельфи. Регион введен для простоты проверки.
сдвиги на 8 влево-вправо - чтобы работать в целочисленной арифметике.

Отмечу, что в Windows GDI есть функция GradientFill, которая умеет рисовать подобные вещи.

Код

var
  V: array[0..2] of TPoint;
  dx, dy, Denom, sa, ta: Integer;
  R, G, B: array[0..2] of Byte;
  hr: HRgn;
  s, t: Integer;
  rr, gg, bb: Byte;
begin
  V[0] := Point(100, 20);
  V[1] := Point(300, 80);
  V[2] := Point(150, 250);
  R[0] := 255;
  G[0] := 0;
  B[0] := 0;
  R[1] := 0;
  G[1] := 255;
  B[1] := 0;
  R[2] := 0;
  G[2] := 0;
  B[2] := 255;
  hr := CreatePolygonRgn(V, 3, ALTERNATE);
  Denom := V[2].x * (V[0].y - V[1].y) + V[0].x * (V[1].y - V[2].y) + V[1].x *  (V[2].y - V[0].y);
  sa := V[2].x * V[0].y - V[2].y * V[0].x;
  ta := V[0].x * V[1].y - V[0].y * V[1].x;
  for dy := 20 to 250 do
    for dx := 100 to 300 do
      if PtInRegion(hr, dx, dy) then begin
        s := (sa + dy * (V[0].x - V[2].x) + dx * (V[2].y - V[0].y)) shl 8 div  Denom;
        t := (ta + dy * (V[1].x - V[0].x) + dx * (V[0].y - V[1].y)) shl 8 div   Denom;
        rr := (R[0] * (255 - s - t) + R[1] * S + R[2] * t) shr 8;
        gg := (G[0] * (255 - s - t) + G[1] * S + G[2] * t) shr 8;
        bb := (B[0] * (255 - s - t) + B[1] * S + B[2] * t) shr 8;
        Canvas.Pixels[dx, dy] := RGB(rr, gg, bb);
      end;
  DeleteObject(hr);
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)