Raytracing: krok po kroku cz soft shading

Podobne dokumenty
Raytracing: krok po kroku cz. 7 - doskonałe odbicie lustrzane

Raytracing: krok po kroku

Zaawansowana Grafika Komputerowa

Oświetlenie. Modelowanie oświetlenia sceny 3D. Algorytmy cieniowania.

Animowana grafika 3D. Opracowanie: J. Kęsik.

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Oświetlenie obiektów 3D

WSTĘP DO GRAFIKI KOMPUTEROWEJ

Grafika Komputerowa Wykład 5. Potok Renderowania Oświetlenie. mgr inż. Michał Chwesiuk 1/38

Leszek Stasiak Zastosowanie technologii LINQ w

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

OpenGL oświetlenie. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Wydziału Elektroniki Politechnika Wrocławska

Gry komputerowe: efekty specjalne cz. 2

Julia 4D - raytracing

Co należy zauważyć Rzuty punktu leżą na jednej prostej do osi rzutów x 12, którą nazywamy prostą odnoszącą Wysokość punktu jest odległością rzutu

KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

Szukanie rozwiązań funkcji uwikłanych (równań nieliniowych)

GRK 4. dr Wojciech Palubicki

C++ Przeładowanie operatorów i wzorce w klasach

Gimp - poznaj jego możliwości!

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Ćwiczenie 42 WYZNACZANIE OGNISKOWEJ SOCZEWKI CIENKIEJ. Wprowadzenie teoretyczne.

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Implementacja filtru Canny ego

PROJEKT FIRMY BUDOWLANEJ

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

3. Macierze i Układy Równań Liniowych

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Model oświetlenia. Radosław Mantiuk. Wydział Informatyki Zachodniopomorski Uniwersytet Technologiczny w Szczecinie

Podstawy Programowania Obiektowego

Pole magnetyczne magnesu w kształcie kuli

Lista dwukierunkowa - przykład implementacji destruktorów

Podstawy POV-Ray a. Diana Domańska. Uniwersytet Śląski

Technologie i usługi internetowe cz. 2

7. Pętle for. Przykłady

O sięganiu głębiej CZWARTY WYMIAR

TEMAT : KLASY DZIEDZICZENIE

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Programowanie strukturalne i obiektowe. Funkcje

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Aleksandra Zając. Raport. Blender. Pokemon: Eevee

10. Programowanie obiektowe w PHP5

Plan wykładu. Akcelerator 3D Potok graficzny

Wyznaczanie stałej słonecznej i mocy promieniowania Słońca

Zmienne losowe i ich rozkłady

Microsoft Small Basic

MNOŻENIE W SYSTEMACH UZUPEŁNIENIOWYCH PEŁNYCH (algorytm uniwersalny)

MATERIAŁ ĆWICZENIOWY Z MATEMATYKI

Oświetlenie w OpenGL. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 8. Światło otaczajace. Światło rozproszone.

Środowisko programistyczne GEANT4

Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego

Zastosowania Robotów Mobilnych

Podłączanie bibliotek Zapis danych do pliku graficznego Generowanie promienia pierwotnego Import sceny z pliku Algorytm ray tracingu

Rysowanie punktów na powierzchni graficznej

Programowanie obiektowe i zdarzeniowe

Programowanie Obiektowe Ćwiczenie 4

Wyjątki (exceptions)

Co łączy te krzywe? (cz.2) W ostatnim artykule zajęliśmy się okręgiem i elipsą. Teraz czas na kolejną oryginalną krzywą parabolę.

Ćwiczenie 1 Galeria zdjęć

programowanie w oparciu o platformę netbeans w praktyce

Sieciowe Technologie Mobilne. Laboratorium 2

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Programowanie obiektowe i C++ dla matematyków

1 Nierówność Minkowskiego i Hoeldera

Informatyka I: Instrukcja 4.2

Grafika 3D program POV-Ray - 1 -

Algorytm SAT. Marek Zając Zabrania się rozpowszechniania całości lub fragmentów niniejszego tekstu bez podania nazwiska jego autora.

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej.

Programowanie gier komputerowych Tomasz Martyn Wykład 6. Materiały informacje podstawowe

Klasy i obiekty cz I Klasy, obiekty, podstawy używania obiektów

Podział sieci na podsieci wytłumaczenie

Ciała i wielomiany 1. przez 1, i nazywamy jedynką, zaś element odwrotny do a 0 względem działania oznaczamy przez a 1, i nazywamy odwrotnością a);

Podstawy programowania obiektowego

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

RENDERING W CZASIE RZECZYWISTYM. Michał Radziszewski

Programowanie w Baltie klasa VII

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Gra Labirynt Zajęcia 5

Grafika komputerowa. Model oświetlenia. emisja światła przez źródła światła. interakcja światła z powierzchnią. absorbcja światła przez sensor

Generatory. Michał R. Przybyłek

Lista, Stos, Kolejka, Tablica Asocjacyjna

OPTYKA GEOMETRYCZNA I INSTRUMENTALNA

1 Układy równań liniowych

Prawdopodobieństwo i statystyka

Grafika realistyczna. Oświetlenie globalne ang. global illumination. Radosław Mantiuk

4/4/2012. CATT-Acoustic v8.0

SPRAWDZIAN NR 1. I promienie świetlne nadal są równoległe względem siebie, a po odbiciu od powierzchni II nie są równoległe względem siebie.

Synteza i obróbka obrazu. Tekstury. Opracowanie: dr inż. Grzegorz Szwoch Politechnika Gdańska Katedra Systemów Multimedialnych

użytkownika 1 Jak wybrać temat pracy 2 Spis treści 3 Część pierwsza problematyka 4 Część druga stosowane metody 5 Część trzecia propozycja rozwiązania

Przekształcanie wykresów.

GRAKO: ŚWIATŁO I CIENIE. Modele barw. Trochę fizyki percepcji światła. OŚWIETLENIE: elementy istotne w projektowaniu

Tworzenie i wykorzystanie usług sieciowych

Zastosowanie CP-grafów do generacji siatek

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Co to jest wektor? Jest to obiekt posiadający: moduł (długość), kierunek wraz ze zwrotem.

Śledzenie promieni w grafice komputerowej

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Parametryzacja obrazu na potrzeby algorytmów decyzyjnych

Luty 2001 Algorytmy (7) 2000/2001

Transkrypt:

Raytracing: krok po kroku cz. 10 - soft shading I. Co/Dlaczego? Kolejnym elementem który na naszych obrazach jest zawsze nierealistycznie ostry są cienie (ang. hard shadows). Dzieje się tak dlatego że źródła światła w prawdziwym świecie mają pewną niezerową wielkość - a my używamy światła punktowego (point light). W tym artykule zajmiemy się symulacją nieostrych, miękkich cieni (ang. soft shadows). (po lewej - nasz cel, czyli soft shadow, po prawej - to co jest obecnie, czyli hard shadow) I. Kilka pomysłów Na świecie nie wszystko można podzielić jednoznacznie podzielić na światło i cień. W momencie kiedy część źródła światła dochodząca do danego punktu jest zasłonięta przez inny obiekt pojawia się półcień. Niestety, dokładne obliczenie jak dużo światła dociera do obiektu byłoby zadaniem bardzo trudnym, powolnym, oraz niemożliwym do zrealizowania w sposób ogólny dla dowolnego obiektu. Na szczęście, napisałem `dokładne obliczenie` - nie jesteśmy jeszcze na straconej pozycji. Na ratunek przybywa po raz kolejny sampling... W jaki sposób wykorzystać sampling do symulowania miękkich cieni? Możemy przetestować kilka różnych ścieżek którymi światło nadchodzi do obiektu i oszacować na tej podstawie ilość docierającego światła (patrz - ilustracja). Pierwszym, naiwnym podejściem jest rzucenie promieni jednorodnie we wszystkich kierunkach dookoła i sprawdzanie czy trafiły na źródło światła: 1

Jeśli ktoś lubi doświadczenia i chciałby przetestować ten sposób w praktyce - należy wziąć kamień (reprezentujący promień) do rąk, zamknąć oczy, obrócić się kilka razy dookoła i rzucić kamieniem. Jeśli kamień trafi w lampę albo inne źródło światła - światło dociera do miejsca gdzie rzucający stoi. Jeśli kamień trafi w przeszkodę, jak ścianę, wiemy że z tego kierunki nie dociera światło. Należy eksperyment powtórzyć wielokrotnie - im więcej razy kamień trafi w światło na, powiedzmy, sto rzutów, w tym jaśniejszym stoimy miejscu (więcej lamp było dookoła). Taki sposób jest bardzo niewydajny -w przypadku na przykład żarówki znajdującej się w pewnej odległości, szansa na to że losowo skierowany promień (rzucony kamień) z odległego punktu w nią trafi jest bardzo mała - większość sceny będzie kompletnie czarna, ponieważ najczęściej nie uda nam się trafić ani jednym promieniem w źródło światła. Na szczęście jest lepszy sposób - możemy odwrócić sposób myślenia i śledzić promienie od światła w kierunku cieniowanego punktu: Taki sposób jest dużo wydajniejszy. Jeśli przyjąć znowu porównanie promienia do kamienia, to tak jakby lampa w pokoju nagle zyskała świadomość i zaczęła rzucać w nas kamieniami. Już po kilku rzuconych kamieniach poszkodowany możne dość trafnie określić jak bardzo jest odsłonięty przed rozwścieczoną lampą. 2

Ponieważ i tak wykonujemy antyaliasing, problem jeszcze się upraszcza - dla każdego piksela tak czy inaczej testujemy wiele promieni, więc obliczanie stosunku `trafiających` i `zablokowanych` promieni dostajemy za darmo (jeśli na przykład do piksela, przy użyciu soft shadingu, dojdzie 12 promieni a 4 zostaną zablokowane przez inny obiekt, suma wchodzącego światła wyniesie 3/4 pełnej jasności - ponieważ 12 promieni liczymy normalnie, a 4 promienie pomijamy). Czyli tak - nasz dotychczasowy (przedstawiony w poprzednich artykułach) sposób postępowania można podsumować tak: 1. Sprawdź czy pomiędzy światłem a cieniowanym punktem jest przeszkoda 2. Jeśli nie, wkład światła wynosi zero. Jeśli tak, licz dalej normalnie. A dodając miękkie cienie, będziemy działać tak: 1. Wybierz punkt na powierzchni światła 2. Sprawdź czy pomiędzy punktem na powierzchni światła a cieniowanym punktem jest przeszkoda 3. Jeśli nie, wkład światła wynosi zero. Jeśli tak, licz dalej normalnie. Wygląda wystarczająco prosto... II. Implementacja Zaczniemy od stworzenia od nowa klasy światła - powinna ona, podobnie ja poprzednia, przechowywać kolor, oraz dodatkowo udostępniać metodę Sample() zwracającą punkt leżący na powierzchni źródła światła. Uprościmy sobię trochę pisanie, i zaimplementujemy jedynie kuliste źródła światła, ponieważ oszczędzi nam to tworzenia dodatkowego interfejsu i klas, a strata w większości przypadków będzie zerowa. Za pomocą tej jednej klasy będziemy symulować jednocześnie światło obszarowe (ang. area light) i światło punktowe (jako światło obszarowe z zerowym promieniem) - nazwiemy ją więc po prostu Light. Tak więc musimy znaleźć sposób generowania punktów na powierzchni kuli - wykorzystamy do tego metodę zaprezentowaną na przykład na tej stronie: http://www.altdevblogaday.com/2012/05/03/generating-uniformly-distributed-points-on-sphere/ Jeśli kogoś interesuje w jaki sposób został wyprowadzony ten wzór (żeby nie dublować materiału, obliczenia nie są tutaj kopiowane), może przeanalizować to: http://repository.upenn.edu/cgi/viewcontent.cgi?article=1188&context=cis_reports Kroki wykonywane w tym algorytmie można, jak zaprezentowano w pierwszym liknu, podsumować następująco: 1. Wybrać współrzędną z z zakresu [ 1;1] 2. Wybrać współczynnik t z zakresu [ 0;2π ] 3. 4. 5. 2 r = 1 z x = r * cos( t) y = r * sin( t) Mapowanie sampli na powierzchnię kuli, korzystając z przedstawionego algorytmu, realizowane jest taką oto prostą funkcją: Vector3 RemapSampleToUnitSphere(Vector2 sample) double z = 2 * sample.x - 1; double t = 2 * Math.PI * sample.y; double r = Math.Sqrt(1 - z * z); return new Vector3( r * Math.Cos(t), r * Math.Sin(t), z); 3

I... to właściwie tyle jesli chodzi o pisanie klasy światła. Możemy spokojnie dopisać resztę, czyli konstruktory i obsługę przypadku światła punktowego: class Light Vector3 center; double radius; Sampler sampler; ColorRgb color; // Konstruktor udający światło punktowe public Light(Vector3 position, ColorRgb color) : this(position, color, null, 0) // pełny konstruktor public Light(Vector3 center, ColorRgb color, Sampler sampler, double radius) this.center = center; this.radius = radius; this.sampler = sampler; this.color = color; public Vector3 Sample() if (radius == 0) return center; // symulowanie światła punktowego var sample = sampler.single(); return center + RemapSampleToUnitSphere(sample) * radius; Vector3 RemapSampleToUnitSphere(Vector2 sample) double z = 2 * sample.x - 1; double t = 2 * Math.PI * sample.y; double r = Math.Sqrt(1 - z * z); return new Vector3( r * Math.Cos(t), r * Math.Sin(t), z); public ColorRgb Color get return color; III. Łączenie w całość Teraz pozostaje dostosować resztę systemu tak żeby działała z nowym światłem. W tym celu musimy zmienić wszystkie wystąpienia poprzedniej, przestarzałej już klasy PointLight na nową klasę Light. Nie jest ich aż tak dużo jak mogłoby się wydawać. Zaczynając od klasy World, pojawia się ona w liście świateł na świecie: List<PointLight> lights; Co zamieniamy, razem z operującymi na niej metodami, na List<Light> lights; Dalej, musimy zmienić fragment w klasie Phong (i analogicznie w PerfectDiffuse) w związku z tym że znikła nam właściwość Position. Tak więc zmieniamy ten kod: Vector3 indirection = (light.position - hit.hitpoint).normalized; double diffusefactor = indirection.dot(hit.normal); if (diffusefactor < 0) continue; 4

if (hit.world.anyobstaclebetween(hit.hitpoint, light.position)) continue; Musimy pobrać pozycję światła za pomocą metody.sample() i użyć jej zamiast light.position: Vector3 lightpos = light.sample(); Vector3 indirection = (lightpos - hit.hitpoint).normalized; double diffusefactor = indirection.dot(hit.normal); if (diffusefactor < 0) continue; if (hit.world.anyobstaclebetween(hit.hitpoint, lightpos)) continue; IV. Wyniki Jak zwykle, pod koniec wypada zaprezentować działanie kodu przedstawionego w artykule. Żeby użyć nowego, obszarowego światła w renderowanej scenie należy wykonać dwa kroki: 1) Stworzyć sampler dla światła: Sampler arealightsampler = new Sampler( new Jittered(0), // generator new SquareDistributor(),// dystrybutor SampleCt, // ilość sampli 97); // ilość zestawów sampli 2) Stworzyć samo światło: world.addlight(new Light( new Vector3(6, 2, 0), // pozycja światła Color.White, // kolor światła arealightsampler, // sampler 2)); // promień Im większy promień światła tym bardziej rozmyte krawędzie cienia - za to przy wielkości światła równej zero, otrzymujemy zupełnie ostre cienie, identyczne do dotychczasowych: 5

Pozostaje dodać wariację na temat jedynej słusznej sceny z trzema kulami, tym razem w trochę 'mroczniejszym' nastroju: 6