Градиенты

Тема в разделе "Delphi - Multimedia, Графика, Игры", создана пользователем liney, 2 авг 2010.

  1. liney

    liney Гость

    Добрый день! Подскажите пожалуйста, каким образом можно нарисовать поверхность с градиентной заливкой типа "Цветовой спектр". Не важно, будет ли это через OpenGL или примитивно. Например, поверхность строится из небольшого количества точек, каждой из которой соответствует определённый цвет. Необходимо построить плавные переходы между цветами. И спроецировать в 2D (что-то вроде карты географических высот, где горы - тёмно-коричневые, а глубины - фиолетовые). Заранее благодарен.
     
  2. Dock1100

    Dock1100 :-]

    Регистрация:
    9 ноя 2009
    Сообщения:
    678
    Симпатии:
    0
    Код (Delphi):
    //смешивание цветов
    function MixColors(fg,bg:Tcolor; trans:real):Tcolor;
    var r_f,g_f,b_f,r_b,g_b,b_b,r,g,b:byte;
    begin
    if trans>1 then trans:=1;
    if trans<0 then trans:=0;
    R_f := getrvalue(fg);
    G_f := getgvalue(fg);
    B_f := getbvalue(fg);
    R_b := getrvalue(bg);
    G_b := getgvalue(bg);
    B_b := getbvalue(bg);
    r:=round(trans*r_b+(1-trans)*r_f);
    g:=round(trans*g_b+(1-trans)*g_f);
    b:=round(trans*b_b+(1-trans)*b_f);
    MixColors:=rgb(r,g,b);
    end;

    //градиентная заливка
    procedure fill_gradient(Rect:Trect; Canvas:Tcanvas; start_color,end_color:TColor; Horizontal,Reverse:boolean);
    var i,j,w,h:integer;
    tmp_col:Tcolor;
    begin
    if reverse then
    begin
    tmp_col:=start_color;
    start_color:=end_color;
    end_color:=tmp_col;
    end;
    if horizontal then
    for i := rect.Left to rect.Right do
    for j := rect.Top to rect.Bottom do
    Canvas.Pixels[i,j]:=mixcolors(end_color,start_color,(i-rect.Left+1)/(rect.Right-rect.Left+1))
    else
    for i := rect.Left to rect.Right do
    for j := rect.Top to rect.Bottom do
    Canvas.Pixels[i,j]:=mixcolors(end_color,start_color,(j-rect.Top+1)/(rect.Bottom-rect.Top+1));
    end;

    //использование
    procedure TForm5.Button1Click(Sender: TObject);
    begin
    fill_gradient(paintbox1.ClientRect,paintbox1.Canvas,rgb(255,0,0),rgb(0,255,255),false,false);
    end;
    ЗЫ если вместо отрисовки каждого пикселя рисовать линию, то будет намного быстрей
     
  3. Dock1100

    Dock1100 :-]

    Регистрация:
    9 ноя 2009
    Сообщения:
    678
    Симпатии:
    0
    Вот, рисует спектр
    Код (Delphi):
    //смешивание цветов
    function MixColors(fg,bg:Tcolor; trans:real):Tcolor;
    var r_f,g_f,b_f,r_b,g_b,b_b,r,g,b:byte;
    begin
    if trans>1 then trans:=1;
    if trans<0 then trans:=0;
    R_f := getrvalue(fg);
    G_f := getgvalue(fg);
    B_f := getbvalue(fg);
    R_b := getrvalue(bg);
    G_b := getgvalue(bg);
    B_b := getbvalue(bg);
    r:=round(trans*r_b+(1-trans)*r_f);
    g:=round(trans*g_b+(1-trans)*g_f);
    b:=round(trans*b_b+(1-trans)*b_f);
    MixColors:=rgb(r,g,b);
    end;

    //градиентная заливка
    procedure fill_gradient(Rect:Trect; Canvas:Tcanvas; start_color,end_color:TColor; Horizontal,Reverse:boolean);
    var i,j,w,h:integer;
    tmp_col:Tcolor;
    begin
    canvas.Pen.Width:=1;
    if reverse then
    begin
    tmp_col:=start_color;
    start_color:=end_color;
    end_color:=tmp_col;
    end;
    if horizontal then
    for i := rect.Left to rect.Right do
    begin
    canvas.Pen.Color:=mixcolors(end_color,start_color,(i-rect.Left+1)/(rect.Right-rect.Left+1));
    canvas.MoveTo(i,rect.Top);
    canvas.LineTo(i,rect.Bottom);
    end
    else
    for j := rect.Top to rect.Bottom do
    begin
    canvas.Pen.Color:=mixcolors(end_color,start_color,(j-rect.Top+1)/(rect.Bottom-rect.Top+1));
    canvas.MoveTo(rect.Left,j);
    canvas.LineTo(rect.Right,j);
    end;
    end;

    //рисуем спектр
    procedure TForm6.Button1Click(Sender: TObject);
    var h,w:integer;
    bmp:Tbitmap;
    begin
    bmp:=Tbitmap.Create;
    bmp.Width:=paintbox1.Width;
    bmp.Height:=paintbox1.Height;
    w:=paintbox1.Width div 6;
    h:=paintbox1.Height;
    //рисуем тьонкую линию с цветами
    fill_gradient(bounds(0,0,w,1),bmp.canvas,rgb(255,0,0),rgb(255,255,0),true,true);
    fill_gradient(bounds(w,0,w,1),bmp.canvas,rgb(255,255,0),rgb(0,255,0),true,true);
    fill_gradient(bounds(w*2,0,w,1),bmp.canvas,rgb(0,255,0),rgb(0,255,255),true,true);
    fill_gradient(bounds(w*3,0,w,1),bmp.canvas,rgb(0,255,255),rgb(0,0,255),true,true);
    fill_gradient(bounds(w*4,0,w,1),bmp.canvas,rgb(0,0,255),rgb(255,0,255),true,true);
    fill_gradient(bounds(w*5,0,w,1),bmp.canvas,rgb(255,0,255),rgb(255,0,0),true,true);
    //рисуем линии сверху вниз
    for i := 0 to bmp.Width - 1 do
    fill_gradient(bounds(i,1,1,h-1),bmp.canvas,bmp.Canvas.Pixels[i,0],rgb(132,132,132),false,true);
    //rgb(132,132,132) - цвет который бедет снизу
    paintbox1.canvas.draw(0,0,bmp);
    bmp.free;
    end;
     
  4. liney

    liney Гость

    Большое спасибо, но дело немножко в другом. Как смешать два цвета - это более-менее понятно, непонятно следующее. Допустим существует сетка, в простейшем случае из 9 точек (вершины, центр и половины сторон квадрата - как пример). Все 9 точек имеют какой-то цвет (может быть одинаковый, а может и все разный). Если рисовать заливку в каждом из пикселей, располагающихся между этими заданными точками, то как определять воздействующие на данную рисуемую точку цвета заданных 9-ти точек? Допустим, берём пиксели, лежащие на линии, соединяющей две соседние точки по вертикали - тогда всё понятно - между ними будет градиентная линейная заливка; по горизонтальной линии - так же. А вот всё то, что расположено между этими линиями? Иными словами, необходима градиентная заливка на поверхности.
     
  5. EdgarWine

    EdgarWine Гость

    Хм... Вопрос хороший... Чтот тоже не могу представить зависимость...
    Тогда быстрее и проще на OGL будет...))

    Код (Delphi):
    procedure TForm1.Button3Click(Sender: TObject);
    begin
    glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, ClientWidth, ClientHeight);
    glLoadIdentity;
    gluOrtho2D(-ClientWidth div 2, ClientWidth div 2, -ClientHeight div 2, ClientHeight div 2);
    glBegin(GL_TRIANGLE_FAN);
    glColor3ub(0, 0, 0);
    glVertex2f(0, 0);
    glColor3ub(255, 0, 0);
    glVertex2f(-128, 128);
    glColor3ub(255, 127, 0);
    glVertex2f(0, 128);
    glColor3ub(0, 255, 0);
    glVertex2f(128, 128);
    glColor3ub(0, 0, 255);
    glVertex2f(128, 0);
    glColor3ub(0, 0, 255);
    glVertex2f(128, -128);
    glColor3ub(127, 0, 255);
    glVertex2f(0, -128);
    glColor3ub(255, 255, 255);
    glVertex2f(-128, -128);
    glColor3ub(255, 0, 255);
    glVertex2f(-128, 0);
    glColor3ub(255, 0, 0);
    glVertex2f(-128, 128);
    glEnd;
    SwapBuffers(DC);
    end;
     

Поделиться этой страницей