BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











Tworzenie cieni pod obiektami graficznymi.

21-01-2005 13:44 | Agita
Przy rysowaniu cienia można zastosować różne techniki, poczynając od najprostszej „plamy” pod obiektem, a kończąc na zastosowaniu metod gradientowych i zaokrąglania rogów. W artykule chciałabym opisać cztery metody rysowania cienia, w których wykorzystam bibliotekę System.Drawing oraz System.Drawing.Drawing2D.

Wstęp

 

Kiedy umieszczamy w aplikacji obiekty graficzne, często zdarza się, iż wyglądają one sztucznie, nienaturalnie. Bardzo trudno jest przedstawić na scenie naturalnie wyglądającą grafikę bez narysowania cienia.

Przy rysowaniu cienia można zastosować różne techniki, poczynając od najprostszej „plamy” pod obiektem, a kończąc na zastosowaniu metod gradientowych i zaokrąglania rogów. W artykule chciałabym opisać cztery metody rysowania cienia, w których wykorzystam biblioteki System.Drawing oraz System.Drawing.Drawing2D.

Do zademonstrowania możliwości tworzenia cieni, zaprezentuję prosty przykład. Będzie to rysowanie cieni pod zwykłymi prostokątami, ale przedstawione metody rysowania cienia można zastosować do grafik różnych kształtów.

 

 

 „Plama” pod obiektem

 

Najprostszym sposobem wyświetlenia cienia jest narysowanie pod obiektem graficznym szarego obiektu o tych samych wymiarach, lecz przesuniętego na płaszczyźnie o pewną wartość. Zakładając, że obiekty będą sprawiały wrażenie oświetlonych z lewego górnego rogu, przesunięcie cienia będzie w płaszczyźnie X w prawo, a płaszczyźnie Y w dół.

 

[Kod C#]

public void CienProstokataZwykly(Graphics g, Rectangle obszarCienia)

{

int przesuniecie = 10; //przesuniecie cienia
obszarCienia.X += przesuniecie;
obszarCienia.Y += przesuniecie;
SolidBrush pedzel = new SolidBrush(Color.Gray); //definicja pedzla
GraphicsPath path = new GraphicsPath(); //definicja sciezki graficznej
path.AddRectangle(obszarCienia); //nadanie ścieżce graficznej pożądanego kształtu
g.FillPath(pedzel, path); //wypełnienie kształtu określonego przez ścieżkę path 
//kolorem określonym przez pędzel

}

Cień rysujemy tą samą metodą, którą rysowaliśmy prostokąt, czyli definiujemy jednokolorowy pędzel typu SolidBrush. Do wypełnienia prostokąta cienia użyję szarego koloru (Color.Gray). Ze względu na ogólność rozwiązania do rysowania obrzeża zastosuję klasę GraphicsPath, którą później wykorzystam przy rysowaniu zaokrągleń rogów cienia.

Ostatnim krokiem będzie wypełnienie zdefiniowanego kształtu wybranym pędzlem, co wykonuje metoda FillPath klasy Graphics.

Efekty tej metody rysowania cienia nie są zadowalające. Cień wygląda bardzo sztucznie i nie komponuje się z resztą sceny – przysłania obiekty leżące pod nim.

 

 

Rys. 1. Cień – szara „plama”

 

 

Cień półprzezroczysty

 

Metoda wykonania cienia półprzezroczystego jest równie prosta, co pierwsza. Natomiast otrzymany wynik wydaje się być o wiele lepszy. Jedyną zmianą w kodzie metody jest deklaracja koloru pędzla.

 

                                  

[Kod C#]

Color kolor = Color.FromArgb( 100, Color.Black);

 

Aby cień był półprzezroczysty, musimy zdefiniować zmienną typu Color, która oprócz określenia koloru będzie miała zdefiniowaną składową alpha – parametr przezroczystości. Alfa przyjmuje wartości z zakresu od 0 do 255, przy czym 0 jest całkowicie przezroczyste, a 255 to nasycenie koloru całkowicie nieprzezroczyste. W przykładowym programie składowa alpha ma wartość 100.

Oto otrzymany efekt:

 

 

Rys. 2. Cień półprzezroczysty

 

Jak widać na rys. 2, cienie różnych obiektów w miejscach nakładania się na siebie wzmacniają się. Lepiej widać ten efekt na rys. 3, gdzie usunięto z obrazu prostokąty, pozostawiając same cienie.

 

  

Rys. 3. Wzmocnienie półprzezroczystych cieni.

 

 

Cień z zastosowaniem gradientu

 

Jeszcze lepsze efekty można uzyskać poprzez zastosowanie pędzla gradientowego. Wymaga to zdefiniowania pędzla typu PathGradientBrush i określenia kilku jego własności. Przede wszystkim należy zdefiniować kolory, jakich użyjemy w gradiencie. W przypadku użycia gradientu do rysowania cienia, będzie to kolor czarny o różnym współczynniku przezroczystości, aż do całkowicie przezroczystego. Zatem punkt centralny gradientu został określony jako półprzezroczysty kolor czarny o współczynniku alpha równym 180. Natomiast kolor na brzegu gradientu będzie całkowicie przezroczysty – w przykładzie kolor czarny o współczynniku alpha równym 0.

 

                                  

[Kod C#]

Color centerColor = Color.FromArgb(180, Color.Black); //kolor w centrum gradientu
Color surroundColor = Color.FromArgb(0, Color.Black); //kolor otaczający centrum gradientu
Color[] colors = { surroundColor };   //zbiór kolorów poza centrum gradientu
PathGradientBrush pthGrBrush = new PathGradientBrush(path);
pthGrBrush.CenterColor = centerColor; //przypisanie koloru centrum gradientu
pthGrBrush.SurroundColors = colors //przypisanie kolorów otoczenia centrum gradientu
pthGrBrush.CenterPoint = new Point(r.X+r.Width/2, r.Y+r.Height/2); //centralny punkt gradientu
pthGrBrush.FocusScales = new PointF(1-3*((float)z/(float)r.Width),1-3*((float)z/(float)r.Height));
// współczynnik określający moment przejscia kolorów w gradiencie

 

Definiując pędzel typu PathGradientBrush, należy podać ścieżkę graficzną (GraphicsPath) związaną z danym pędzlem. Ścieżka ta będzie określała granice „rozchodzenia” się gradientu. Właściwościami, które należy zdefiniować są kolor w centrum (CenterColor) gradientu oraz kolory otaczające to centrum (SurroundColors). Konieczne jest wcześniejsze zadeklarowanie tablicy kolorów, która zostanie przypisana właściwości SurrondsColors. Właściwość ta przyjmuje tablice kolorów o maksymalnej długości równej liczbie punktów ścieżki użytej w konstruktorze pędzla. Dla prostokątnego obszaru byłyby to zatem maksymalnie cztery kolory. Jednak, aby narysować cień, tablica ta ma jeden całkowicie przezroczysty kolor. Definiujemy również właściwość CenterPoint, która określa miejsce punktu koloru centralnego gradientu. W przykładowym programie jest do środek prostokąta.

Bardzo istotną właściwością pędzla gradientowego jest FocusScales, typu PointF. Określa ona przejście kolorów w gradiencie. Zmienne x i y FocusScales zawierają się w przedziale od 0 do 1. Im bardziej w danym wymiarze wartość zbliża się do 0, tym początek przejścia koloru centrum gradientu w kolory otoczenia zbliża sie do punktu CenterPoint. Natomiast im bliżej wartości 1, tym bardziej przejście gradientu zbliża się do krawędzi. W przykładowym programie wyliczony został algorytm, który gwarantuje odpowiednią wartość właściwości dla prostokątów różnych rozmiarów i zmiennego parametru przesunięcia cienia względem prostokąta. Przykłady rozchodzenia się gradientu dla różnych wartości właściwości FocusScales:

                        


Rys. 4a. PointF((float)0,(float)0)  


Rys. 4b. PointF((float)0.5,(float)0.5)


   Rys. 4b. PointF((float)0.9,(float)0.9)

 

Otrzymane rezultaty są prawie zadowalające, jednak do życzenia pozostawiają jeszcze rogi cienia, które są wyraźnie ostro zakończone.

 

Rys. 5. Cień metodą gradientową

 

 

Cień z zastosowaniem gradientu i zaokrąglonymi rogami.

 

Ostatnią modyfikacją w rysowaniu cienia, którą przedstawię, jest zaokrąglenie rogów. W tym celu użyję metody obiektu typu GraphicsPath, która dodaje do ścieżki graficznej zbiór linii, zdefiniowanych przez tablicę punktów. Punkty te tworzą obrys cienia:

 

                                  

[Kod C#]

Point [] points = new Point[7]; //tablica punktów

// definicje posczególnych punktów tworzących prostokąt z zaokrąglonymi rogami
points[0] = new Point(r.X, r.Y);
points[1] = new Point(r.X, r.Y+r.Height-z);
points[2] = new Point(r.X+z, r.Y+r.Height);
points[3] = new Point(r.X+r.Width-z/2, r.Y+r.Height);
points[4] = new Point(r.X+r.Width, r.Y+r.Height-z/2);
points[5] = new Point(r.X+r.Width, r.Y+z);
points[6] = new Point(r.X+r.Width-z, r.Y);
path.AddLines(points); //dodanie do ścieżki graficznej zbioru punktów

 

Ostateczny efekt przedstawiony na rys. 6. jest całkiem realistyczny.

 

 

Rys. 6. Cień metodą gradientową z zaokrąglonymi rogami

 

 

Podsumowanie

 

Mam nadzieję, iż artykuł ten przybliżył nieco czytelnikowi zagadnienia związane z tworzeniem dwuwymiarowej grafiki 2D w środowisku C#.NET. Uważam, że zademonstrowane zastosowanie biblioteki System.Drawing oraz System.Drawing.Drawing2D do tworzenia cienia pod obiektami może być przydatne przy projektowaniu interfejsu użytkownika.

 

Załączniki:

Podobne artykuły

Komentarze 3

User 131335
User 131335
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0

Praktyczny, zwiezly i sprawnie jezykowo napisany tekst. Konkretne rozwiazanie konkretnego problemu. Gratulacje!

User 131335
User 131335
0 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0
... to ja Ci przekaze, jak sie spotkamy :).
May_Be
May_Be
16 pkt.
Nowicjusz
21-01-2010
oceń pozytywnie 0

...gdyby tak wszystkie artyqły były tak klarownie napisane...

pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.