Пятница, 29 Марта 2024, 09:49

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Форум игроделов » Программирование » Общие обсуждения программистов » Градиент
Градиент
AlkoshaДата: Суббота, 21 Июня 2014, 20:00 | Сообщение # 1
участник
Сейчас нет на сайте
Допустим, на вход функции поступают параметры для цветовых переходов от одного цвета до другого.

Вот к примеру color1={r1,g1,b1}; color2={r2,g2,b2}
тут цикл for=0 to len // где len - ширина градиента.
затем линиями line(x1,y1,x2,y2) с цветовыми переходами от color1 до color2.
Как определить для каждого шага в цикле цвет перехода?


Сообщение отредактировал Alkosha - Суббота, 21 Июня 2014, 20:01
wcptДата: Понедельник, 23 Июня 2014, 20:28 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
может, глупо и наивно, но ты не пробовал найти разницу между соответственными компонентами цвета, поделить эти разницы на число шагов, и прибавлять эти разницы к компонентам исходного цвета в цикле? Я не пробовал, просто предположил, вдруг это оно smile

Сообщение отредактировал wcpt - Понедельник, 23 Июня 2014, 20:30
daunДата: Понедельник, 23 Июня 2014, 20:42 | Сообщение # 3
постоянный участник
Сейчас нет на сайте
попробуй среднее арифметическое (или как там его smile
Код
color3=RGB( (r1*shag+r2) div shag+1, (g1*shag+g2) div shag+1, (b1*shag+b2) div shag+1,)
wcptДата: Вторник, 24 Июня 2014, 11:50 | Сообщение # 4
постоянный участник
Сейчас нет на сайте
Автор, ты чего? Пробовал что-либо делать? Посмотри-ка на это (гипотетический си-подобный язык):
Код

int stepnum = 100 //влияет на число оттенков
int width = 100 //ширина полоски
int height = 100 // высота полоски
void Grad (color clr1,color clr2)
{
         int dr = clr2.R-clr1.R;
         int dg = clr2.G-clr1.G;
         int db = clr2.B-clr1.B;

         dr /= stepnum;
         dg /= stepnum;
         db /= stepnum;

         for (int i=0; i<width;i++)
         {
             color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db)
                  
             for (int j=0; j<height; j++)
             {
                 image.putpixel(i,j,_clr)
             }
         }
}



Сообщение отредактировал wcpt - Вторник, 24 Июня 2014, 12:14
AlkoshaДата: Суббота, 05 Июля 2014, 08:08 | Сообщение # 5
участник
Сейчас нет на сайте
Но тут же в теле цикла не происходит никакого изменения
_clr остаётся постоянным.
Код

color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db)


Вот например сие даёт сплошной ярко-красный цвет.

Код

SDL_Color skyColorTop={255,100,100,255};
SDL_Color skyColorBottom={255,10,10,255};

int dr = skyColorBottom.r-skyColorTop.r;
int dg = skyColorBottom.g-skyColorTop.g;
int db = skyColorBottom.b-skyColorTop.b;
dr /= stepnum;
dg /= stepnum;
db /= stepnum;

for(int a=0;a<600;a+=1)
      {
       SDL_SetRenderDrawColor(renderer, skyColorBottom.r+dr,skyColorBottom.g+dg, skyColorBottom.b+db, 255);
       SDL_RenderDrawLine(renderer,0,a,800,a);
      }


Сообщение отредактировал Alkosha - Суббота, 05 Июля 2014, 08:09
daunДата: Суббота, 05 Июля 2014, 11:05 | Сообщение # 6
постоянный участник
Сейчас нет на сайте
1) байт - целое от 0 до 255, выход за пределы ни к чему хорошему не приведет
2) rgb кодируется тремя байтами, на каждый по одному, плюс четвертый альфа (если 32 бита, возможны варианты)
3) если r,g,b по значению близки друг к другу - теряется цвет, пиксель стремится к черно-белому, и наоборот
4) величина дает яркость, 0 - темный, 255 - светлый
5) смешивание двух цветов определяется по средней - (r1+r2)/2 (g1+g2)/2 (b1+b2)/2
6) манипуляции с цветом (в фильтрах например) только с использованием процентов (гарантирует значение в пределах байта)
r:=r+trunc((256-r)/100*10); g:=g+trunc((256-g)/100*10); b:=b+trunc((256-b)/100*10);

Код

procedure GraG(bit:TBitMap; col1:TColor; col2:TColor);
var a:integer; r1,g1,b1,r2,g2,b2:byte;
begin
     r1:=GetRValue(col1); g1:=GetGValue(col1); b1:=GetBValue(col1);
     r2:=GetRValue(col2); g2:=GetGValue(col2); b2:=GetBValue(col2);
     for a:=0 to bit.Width-1 do begin
         bit.Canvas.Pen.Color:=RGB(trunc(r1-(r1-r2)/(bit.Width-1)*a), trunc(g1-(g1-g2)/(bit.Width-1)*a), trunc(b1-(b1-b2)/(bit.Width-1)*a));
         bit.Canvas.MoveTo(a,0);
         bit.Canvas.LineTo(a,bit.Height);
     end;
end;


wcptДата: Суббота, 05 Июля 2014, 12:02 | Сообщение # 7
постоянный участник
Сейчас нет на сайте
не знаю, если честно, почему у тебя не получается. Я привел частный случай. Его еще нужно подстроить под необходимую длину градиента, которая тут взята для примера. Плюс, при слишком малой ширине весь спектр не будет умещаться в полоску, это тоже надо учесть.

Добавлено (05.07.2014, 11:22)
---------------------------------------------
Цитата Alkosha ()
Но тут же в теле цикла не происходит никакого изменения

я привел пример поточечного заполнения, без линий, учти. И, на всякий случай, clr1 - цвет левой части полоски, clr2 - правой части.

Добавлено (05.07.2014, 11:57)
---------------------------------------------
вот и я. Кое-какие условности были убраны, и теперь все в норме:
Код

                    
const int height = 100;
const int width = 200;
                    
float _dr;
float _db;
float _dg;
float __dr;
float __db;
float __dg;

void Grad(color clr1,color clr2)
{
                          
      _dr = (clr2.R - clr1.R);
      _dg = (clr2.G - clr1.G);
      _db = (clr2.B - clr1.B);

       _dr /= width;
       _dg /= width;
       _db /= width;

       color clr_;

       for (int i = 0; i < width; i++)
       {
            
           __dr += _dr;
           __dg += _dg;
           __db += _db;

           clr_ = RGB(clr1.R + (int)__dr, clr1.G + (int)__dg, clr1.B + (int)__db);

           for (int j = 0; j < height; j++)
           {
               image.putpixel(i, j, clr_);
           }
       }                  
}


Добавлено (05.07.2014, 12:02)
---------------------------------------------
ну и конечно, если захочется линиями, то внутренний цикл убирай, ставь вместо него что-то типа line(i,0,i,height,clr_), если полоска градиента расположена в левом верхнем углу.



Сообщение отредактировал wcpt - Суббота, 05 Июля 2014, 13:52
AlkoshaДата: Воскресенье, 06 Июля 2014, 00:58 | Сообщение # 8
участник
Сейчас нет на сайте
Цитата
ну и конечно, если захочется линиями, то внутренний цикл убирай, ставь вместо него что-то типа line(i,0,i,height,clr_), если полоска градиента расположена в левом верхнем углу.


это и так понятно. Просто в Вашем первом варианте в теле цикла (не там где происходит попиксельное рисование линий), переменная остаётся без изменений.
Код
   for (int i=0; i<width;i++)    
            {    
                color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db)    
                        
         /*
для наглядности закомментируем

          for (int j=0; j<height; j++)    
                {    
                    image.putpixel(i,j,_clr)    
                }    
        */
            }


А что касается Вашего последнего варианта, то даже не знаю, чё я делаю не так.
Градиента никакого.
Сплошной цвет получается
Структура SDL_Color'a - r,g,b,a

Код

SDL_Color skyColorTop={255,0,0,0};
SDL_Color skyColorBottom={0,0,255,255};

SDL_RenderSetScale(renderer,1,1);
SDL_SetRenderDrawBlendMode( renderer, SDL_BLENDMODE_BLEND);

float _dr;
float _db;
float _dg;
float __dr;
float __db;
float __dg;

    _dr = skyColorBottom.r-skyColorTop.r;
    _dg = skyColorBottom.g-skyColorTop.g;
    _db = skyColorBottom.b-skyColorTop.b;

     _dr /= 600;
     _dg /= 600;
     _db /= 600;

for(int a=0;a<600;a+=1)
       {
__dr += _dr;
__dg += _dg;
__db += _db;

SDL_SetRenderDrawColor(renderer, skyColorTop.r + (int)__dr, skyColorTop.g + (int)__dg, skyColorTop.b + (int)__db, 255);
SDL_RenderDrawLine(renderer,0,a,800,a);

       }
}


рисует сплошняком цветом skyColorTop (он же clr1). Как будто к нему прибавляются нули по rgb-каналам.

И даже если бы и прибавлялось что-то, ведь тут вполне возможно переполнение за значение 255 (допустим clr1.r=250, то в установке цвета к нему ещё бы прибавилось сего-нибудь (допустим единицу), то есть он бы резко спал в значение 0)


Сообщение отредактировал Alkosha - Воскресенье, 06 Июля 2014, 00:59
wcptДата: Воскресенье, 06 Июля 2014, 13:23 | Сообщение # 9
постоянный участник
Сейчас нет на сайте
Цитата Alkosha ()
это и так понятно. Просто в Вашем первом варианте в теле цикла (не там где происходит попиксельное рисование линий), переменная остаётся без изменений.

это где же?
Код
color _clr = RGB(clr1.R+dr,clr1.G+dg,clr1.B+db)

тут, что ли? Да, ошибочка, извиняюсь. Тут, по идее должно вместо _clr быть использовано clr1.

могу предположить, что проблемы возникают из-за приведения типов. Как я посмотрел, у SDL_Color r g b задаются как uint8. Ты же __dr __dg __db к int приводишь. Ну а потом они автоматом к uint8 приводятся, если ты пробовал именно тот код, что привел здесь. Не помню всех подробностей, поэтому могу ошибаться. В моем примере я предполагал, что r g b как int задаются. Ну, и конечно, _dr, _dg, _db, __dr, __dg, __db могут быть и отрицательными.

Добавлено (06.07.2014, 13:23)
---------------------------------------------
Ну и еще одна деталь -
Код
SDL_Color skyColorTop={255,0,0,0};            
SDL_Color skyColorBottom={0,0,255,255};

случаем не красный и синий соответственно? Так вот, проблем нет и с ними.

а переполнения быть не может, ведь шаг прибавления _dx постоянен и представлен в пространстве в пределах байта. При том условии, конечно,что при касте к int число округляется до предыдущего целого.


Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 15:50
AlkoshaДата: Воскресенье, 06 Июля 2014, 15:54 | Сообщение # 10
участник
Сейчас нет на сайте
Даже когда создал структуру, результат всё тот же - сплошной цвет, который указан в skyColorTop (он же clr1 )
Код
    struct mycolor
{
     int r;
     int g;
     int b;
} ;
wcptДата: Воскресенье, 06 Июля 2014, 15:57 | Сообщение # 11
постоянный участник
Сейчас нет на сайте
покажи полностью, как используешь, погляжу.
AlkoshaДата: Воскресенье, 06 Июля 2014, 16:31 | Сообщение # 12
участник
Сейчас нет на сайте
Код
     
struct mycolor
{
     int r;
     int g;
     int b;
} ;

public:
void sky()
{

mycolor skyColorTop={255,0,0};
mycolor skyColorBottom={0,0,255};

float _dr;
float _db;
float _dg;
float __dr;
float __db;
float __dg;

  _dr = skyColorBottom.r-skyColorTop.r;
  _dg = skyColorBottom.g-skyColorTop.g;
  _db = skyColorBottom.b-skyColorTop.b;

   _dr /= 600;
   _dg /= 600;
   _db /= 600;

for(int a=0;a<600;a+=1)
     {
__dr += _dr;
__dg += _dg;
__db += _db;

SDL_SetRenderDrawColor(renderer, skyColorTop.r +(int) __dr, skyColorTop.g +(int) __dg, skyColorTop.b +(int) __db, 255);
SDL_RenderDrawLine(renderer,0,a,800,a);

     }
}
wcptДата: Воскресенье, 06 Июля 2014, 16:39 | Сообщение # 13
постоянный участник
Сейчас нет на сайте
я написал, что проблемы, вероятно, из-за того, что у SDL_Color r g b a задаются как uint8, т.е. как беззнаковые числа. То есть,
Код
skyColorTop.r +(int) __dr

должно быть беззнаковым.

А в свою очередь,
Код
(int) __dr

есть число со знаком, т.е. оно должно быть скастовано в беззнаковое число, по сути. Однако что случится, если (int)__dr - отрицательное? Это вполне возможно, а учитывая конкретные цвета - гарантировано. Каким оно будет после приведения, можешь сказать?


Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 16:49
AlkoshaДата: Воскресенье, 06 Июля 2014, 16:53 | Сообщение # 14
участник
Сейчас нет на сайте
Цитата wcpt ()
я написал, что проблемы, вероятно, из-за того, что у SDL_Color r g b a задаются как uint8, т.е. как беззнаковые числа. То есть,


В приведённом мною листинге уже нет SDL_Color .

Тут же своя структура с интами
Код
    struct mycolor   
{   
       int r;   
       int g;   
       int b;   
} ;


Добавлено (06.07.2014, 16:53)
---------------------------------------------
То есть тут -- int + int
Код
skyColorTop.r +(int) __dr


Сообщение отредактировал Alkosha - Воскресенье, 06 Июля 2014, 16:54
wcptДата: Воскресенье, 06 Июля 2014, 17:19 | Сообщение # 15
постоянный участник
Сейчас нет на сайте
хорошо, но это, все же, должно смутить, как минимум:
https://wiki.libsdl.org/SDL_SetRenderDrawColor

Код
int SDL_SetRenderDrawColor(SDL_Renderer* renderer,
                      Uint8         r,
                      Uint8         g,
                      Uint8         b,
                      Uint8         a)

т.е. в этой функции тоже uint8.


Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 17:21
AlkoshaДата: Воскресенье, 06 Июля 2014, 17:24 | Сообщение # 16
участник
Сейчас нет на сайте
Даже если и так, я пробовал так же (Uint8) __dr , ещё когда skyColorTop был SDL_Color'ом. Тот же результат
wcptДата: Воскресенье, 06 Июля 2014, 17:26 | Сообщение # 17
постоянный участник
Сейчас нет на сайте
а это
Цитата Alkosha ()
(Uint8) __dr

и не поможет. Если __dr отрицательное, то как оно может быть корректно представлено в uint8? Я пытаюсь тебя подвести к тому, что сначала надо произвести вычисления с "удобными" типами, а потом результаты (которые, по идее, будут в пределах байта, почему я уже написал) привести к uint8. Ну и вызывать функцию с приведенными к uint8 результатами.


Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 17:34
AlkoshaДата: Воскресенье, 06 Июля 2014, 19:20 | Сообщение # 18
участник
Сейчас нет на сайте
Цитата wcpt ()
а потом результаты (которые, по идее, будут в пределах байта, почему я уже написал)


не важно, будет там инт или байт, так как там интенсивность возрастает от 0 до 255-ти, затем от 256 до 511-ти и так далее.
так же с минусовым знаком.

Я к тому, что
while(!0)
{
SDL_Color rgb;
rgb++;
render();
}

Будет постоянно мигать (постепенно возрастать яркость , затем резко гаснуть, и опять постепенно возрастать по яркости).
wcptДата: Воскресенье, 06 Июля 2014, 22:10 | Сообщение # 19
постоянный участник
Сейчас нет на сайте
Автор, ты вместо того, чтобы спорить, попробовал бы сделать так, как я сказал. Специально для тебя скачал эсдиэл ту поинт зироу, установил, глянул уроки для начинающих, и попробовал эту штуку. А для чего? Чтобы удостовериться, что я был прав c самого начала, и что оно само автоматом все прекрасно приводится? Вот код, полностью, работает, вроде(и без всяких приведений!):

Код
int _tmain(int argc, _TCHAR* argv[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}

SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);

if (win == nullptr){
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return 1;
}

SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
SDL_DestroyWindow(win);
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_Quit();
}

SDL_Color clr1 = { 255, 0, 0, 255 };
SDL_Color clr2 = { 0, 0, 255, 255 };

float _dr = clr2.r - clr1.r;
float _dg = clr2.g - clr1.g;
float _db = clr2.b - clr1.b;

float __dr = 0;
float __db = 0;
float __dg = 0;

_dr /= 600;
_dg /= 600;
_db /= 600;

for (int i = 0; i < 600; i++)
{

__dr += _dr;
__dg += _dg;
__db += _db;

SDL_SetRenderDrawColor(ren, clr1.r + __dr, clr1.g + __dg, clr1.b + __db, 255);

SDL_RenderDrawLine(ren, 0, i, 800, i);
}

SDL_RenderPresent(ren);

SDL_Delay(2000);

SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();

_getch();

return 0;
}


Сообщение отредактировал wcpt - Воскресенье, 06 Июля 2014, 22:42
AlkoshaДата: Понедельник, 07 Июля 2014, 00:03 | Сообщение # 20
участник
Сейчас нет на сайте
странно... так работает. Но не вижу где разница с моим листингом (за исключением названий переменных)...
Форум игроделов » Программирование » Общие обсуждения программистов » Градиент
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг