Градиенты

  • Автор темы liney
  • Дата начала
L

liney

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

Dock1100

Код:
//смешивание цветов
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;

ЗЫ если вместо отрисовки каждого пикселя рисовать линию, то будет намного быстрей
 
D

Dock1100

Вот, рисует спектр
Код:
//смешивание цветов
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;
 
L

liney

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

EdgarWine

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

Код:
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;
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!