Class TRayTracer

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type TRayTracer = class(TObject)

Description

Hierarchy

Overview

Fields

Public Octree: TVRMLBaseTrianglesOctree;
Public Image: TImage;
Public CamPosition: TVector3_Single;
Public CamDirection: TVector3_Single;
Public CamUp: TVector3_Single;
Public ViewAngleDegX: Single;
Public ViewAngleDegY: Single;
Public SceneBGColor: TVector3_Single;
Public PixelsMadeNotifier: TPixelsMadeNotifierFunc;
Public PixelsMadeNotifierData: Pointer;
Public FirstPixel: Cardinal;

Methods

Public procedure Execute; virtual; abstract;

Description

Fields

Public Octree: TVRMLBaseTrianglesOctree;

This describes the actual scene that will be used. Must be set before calling Execute.

Public Image: TImage;

Image where the ray-tracer result will be stored. Must be set before calling Execute.

We will not resize given here Image. Instead we will use it's current size — so you just have to set Image size as appropriate before calling this method.

We will write on image using TImage.SetColorRGB method, so this method must be implemented in Image class you use (it's implemented in all 3 classes TRGBImage, TRGBAlphaImage, TRGBEImage in Images unit, so usually you just don't worry about that).

Dla kazdego pixela w ktorym promien trafia na obiekt ze sceny zapisujemy w obrazku wyliczony kolor RGB sceny w tym miejscu. Nie dotykamy kanalu Alpha obrazka TRGBAlphaImage. (kiedys mialem tu mechanizm obslugi tego kanalu ale zbytnio mi zawadzal a i tak nie byl uzywany, dlatego go wylaczylem). Akceptujemy naturalnie obrazki TRGBEImage i bedziemy w nich zapisywali precyzyjne kolory — de facto format TRGBEImage zaimplementowalem wlasnie po to zeby raytracery w tym module mogly zapisywac obrazki precyzyjnie, z kolorami jako 3xFloat.

Ponadto, gdy uzywasz dowolnego formatu innego niz TRGBEImage (patrzac przyszlosciowo : dowolnego formatu z precyzja i zakresem float) tracisz nie tylko precyzje : kolory 3xSingle sa konwertowane na 3xByte a konwersja Byte->Single jest robiona tak jak VectorMath.Vector3Byte : zakres Single 0-1 jest skalowany na zakres bajtu 0-255, jezeli wartosc Single jest wieksza niz 1 (co jest przeciez zupelnie mozliwe) to jest obcinana do 1. Wiec zapisujac do ikRGB/ikAlpha moze sie okazac ze przy bardzo jasnej scenie wyjdzie ci caly bialy obrazek - podczas gdy przy ikRGBE obrazek mialby po prostu kolory wieksze niz (1.0, 1.0, 1.0) co moznaby zawsze zniwelowac skalowaniem albo korekcja gamma. Ta zaleta formatu RGBE jest pokrotce opisana takze na poczatku dokumentacji do rayhuntera na [http://vrmlengine.sourceforge.net/rayhunter.php].

(Ta wada formatow RGB/Alpha nie bedzie naprawiona w tej funkcji bo niby jak ? Jedynym sensownym rozwiazaniem jest tutaj zapisac obrazek raytracerem w formacie RGBE a potem, po wygenerowaniu calosci, ustalic maksymalna wartosc komponentu i zrobic odpowiednie skalowanie lub korekcje gamma; ale do tego nie musze wcale naprawiac tej funkcji — wiec mozna co najwyzej uznac to za blad rayhuntera i view3dscene ze takiego naprawiania nie robia po uzyciu RaytraceTo1st. Ale: view3dscene zrzuca sprawe na "view3dscene nigdy nie mial realizowac raytracingu do celu innego niz tylko testowanie, tzn. view3dscene nie sluzy do generowania ostatecznych dopieszczonych obrazkow - od tego jest rayhunter". A rayhunter argumentuje ze "zeby to zrobic to w srodku rayhuntera musialbym robic zapis do RGBE i dopiero na koncu konwertowac do RGB : w ten sposob nie tylko komplikuje sobie kod ale takze robienie --write-partial-row staje sie klopotliwe. A wiec, na podobnej zasadzie jak funkcja Execute zwala problem na kod zewnetrzny, tak rayhunter zwala problem na program zewnetrzny. Innymi slowy, zawsze generuj obrazki do RGBE jesli nie chcesz miec tego problemu. Zreszta, Radiance tez tak robi : zawsze zapisuje obrazki do swojego RGBE i potem w czasie post-processingu obrazka umozliwia robienie korekcji kolorow)" )

Wszystkie pixle obrazka zostana zapisane przez raytracer. Kiedys mialem tu mechanizm umozliwiajacy podlozenie pod rendering tla, ale skasowalem to bo bylo malo uzyteczne a bardzo nieeleganckie w zapisie (wymagalo ode mnie rozrozniania czy promien pierw. trafil w scene czy nie; teraz po prostu promien ktory nie trafia w scene przynosi kolor SceneBGColor).

Public CamPosition: TVector3_Single;

Parametry CamPosition, CamDirection, CamUp naturalnie ustawiaja kamere w scenie. Tak jak zwykle, jezeli CamUp i CamDirection nie sa prostopadle to poprawiany jest CamUp aby byc prostopadly (a NIE camDirection).

Public CamDirection: TVector3_Single;

Parametry CamPosition, CamDirection, CamUp naturalnie ustawiaja kamere w scenie. Tak jak zwykle, jezeli CamUp i CamDirection nie sa prostopadle to poprawiany jest CamUp aby byc prostopadly (a NIE camDirection).

Public CamUp: TVector3_Single;

Parametry CamPosition, CamDirection, CamUp naturalnie ustawiaja kamere w scenie. Tak jak zwykle, jezeli CamUp i CamDirection nie sa prostopadle to poprawiany jest CamUp aby byc prostopadly (a NIE camDirection).

Public ViewAngleDegX: Single;

ViewAngleDegX i ViewAngleDegY to rozpietosc obiektywu w stopniach.

Public ViewAngleDegY: Single;

ViewAngleDegX i ViewAngleDegY to rozpietosc obiektywu w stopniach.

Public SceneBGColor: TVector3_Single;
 
Public PixelsMadeNotifier: TPixelsMadeNotifierFunc;

PixelsMadeNotifier, jezeli <> nil, to bedzie wywolywane po zapisaniu kazdego pixla w Image. W ten sposob bedzie mozna wyswietlac obrazek juz w trakcie generowania, jezeli tylko bedzie taka potrzeba. PixelsMadeNotifier dostanie jako parametry liczbe pixli jaka zostala juz zrobiona i PixelsMadeNotifierData (ktory tradycyjnie mozesz dowolnie wykorzystac do wygodnej komunikacji z callbackiem).

Na pytanie KTORE konkretnie pixele zostaly zrobione, tzn. gdzie na obrazku jest to PixelsDoneCount pixli, inaczej mowiac : w jakiej kolejnosci robimy pixle : dla ClassicRayTracera: jak TSwapScanCurve dla PathTracera: zalezy od SFCurveClass;

Wszystko przez to ze SFCurveClass okazaly sie praktycznie bezuzyteczne dla path tracera, niczego tam nie przyspieszaja. Ale byc moze okaza sie bardziej laskawe dla Classic RayTracera. Na razie nie zaimplementowalem jeszcze w ClassicRayTracerze shadow-cache a wiec takze te SFCurveClass sa bez sensu, ale kiedys planuje to zrobic.

Chwilowo powinienes zawsze uzywac w path tracerze BestRaytrSFC aby miec TSwapScanCurve ktore renderuje prosto wierszami. Wiekszych komplikacji nie ma sensu na razie gdziekolwiek wprowadzac skoro uzywanie innych SFC niz renderujace wierszami od dolu do gory jest bezcelowe (dla path tracera) lub niezaimplementowane (dla classic ray tracera).

Remember that pixels not done yet have the same content as they had when you Execute method started. In other words, if you set PixelsMadeNotifier <> nil, then often it's desirable to initialize Image content (e.g. to all SceneBGColor) before calling Execute. Otherwise at the time of Execute call, the pixels not done yet will have undefined colors.

Public PixelsMadeNotifierData: Pointer;
 
Public FirstPixel: Cardinal;

FirstPixel pozwala renderowac obrazki od srodka - normalnie FirstPixel = 0 powoduje ze zaczynamy renderowac od pierwszego pixela i wyrenderujemy caly obrazek. FirstPixel > 0 oznacza ze zaczynamy gdzies dalej, uznajac pierwsze FirstPixel pixeli na Image za juz zrobione (i nie zapisujemy im zadnej wartosci). To jest przydatne do wznawianie dzialania ray tracera poprzednio przerwanego ktory zapisal czesciowo wygenerowany rysunek. FirstPixel musi byc w zakresie 0..Image.Width*Image.Height przy czym wartosc najwieksza (Image.Width*Image.Height) instruuje ray tracera zeby nic nie robil (caly obrazek jest juz wygenerowany).

Zwracam uwage ze pierwszy parametr PixelMadeNotifier uwzglednia fakt tak jakbysmy zrobili juz FirstPixel pixeli, tzn. kolejne wywolania PixelMadeNotifier beda kolejno dostawaly parametry FirstPixel+1, FirstPixel+2 ... itd. az do Image.Width * Image.Height.

Methods

Public procedure Execute; virtual; abstract;

Do ray-tracing: write a ray-traced image into the Image.


Generated by PasDoc 0.11.0 on 2009-01-03 20:36:46