Spotykam się ostatnio z osobliwym podejściem do przeróżnych wiadomości tyczących się programowania. Mogę je określić dość zaskakująco jako nadmiar “chęci rozumienia” lub ewentualnie “nieuzasadnioną dociekliwość”. Dotyczy to bardzo wielu narzędzi używanych w zasadzie każdej dziedzinie programowania – jak języki, środowiska czy biblioteki – oraz większości jego aspektów.
Czym to się objawia? Otóż symptomem jest pragnienie dogłębnego zrozumienia jakiegoś mechanizmu w sposób jak najszerszy i jak najgłębszy jednocześnie – zanim jeszcze spróbuje się go zastosować. Ten pęd to wiedzy dla samej wiedzy skutkuje najczęściej pozyskaniem dużego zasobu informacji, z których sensownym połączeniem i – przede wszystkim – stosowaniem są później pewne, a często spore, kłopoty.
Czy twierdzę więc, że nadmiar wiedzy szkodzi? Bynajmniej. Chodzi mi raczej o chęć zadawania raczej pytań w rodzaju “jak to działa?” niż “jak tego użyć?”. Sądzę bowiem, że zdecydowana większość programistycznej wiedzy ma charakter czysto użytkowy i jako taka jest na tyle przydatna, na ile daje się użyć w praktyce. Koder powinien być raczej przygotowany na poszukiwanie potrzebnych informacji w trakcie rozwiązywania danego problemu, a nie na kompletne poznanie tematu przez przystąpieniem do pracy.
Jeśli aczkolwiek życzymy sobie poznać głębiej jakieś zagadnienie z racji tego, że jest ono interesujące, wszystko jest w porządku. Jeśli jednak chodzi nam tylko o osiągnięcie zamierzonego celu, nie musimy poznawać rozgałęzień każdej drogi, która do niego prowadzi. Jak zawsze, najważniejsze jest zachowanie odpowiedniej równowagi.
Niby kod można pisać w Notatniku, ale własnej równowagi psychicznej chyba lepiej zaopatrzyć się w edytor, który oferuje przynajmniej podświetlanie elementów składniowych języka. Wiadomo przecież, że mnogość kolorów poprawia samopoczucie :)
Co więc zrobić, gdy zamierzamy pisać efekty w języku HLSL (lub bardzo podobnym Cg)? Trzeba zdecydować się na jakieś narzędzie. Możliwych jest kilka wyjść:
Jak widać, nie jesteśmy więc skazani na surową, czarno-białą czcionkę. A to dobrze, bo po dodaniu tej całej skomplikowanej matematyki, dziwnej semantyki dla danych wierzchołków i niezliczonych dyrektyw kompilacji warunkowej, kod shaderów jest już wystarczająco skomplikowany :)
Model subtraktywny programowalnego potoku graficznego (nie ma to jak kilka trudnych słów na początek ;P) charakteryzuje się tym, że kody shaderów są w nim dość rozdęte objętościowo. Wynikową postać shadera otrzymuje się bowiem poprzez wybranie części kodu odpowiadającej aktualnym potrzebom związanym np. z materiałem i oświetleniem. Rzeczone części są wydzielone przy pomocy dyrektyw podobnych do preprocesora z C: #if
, #else
, itd.
Najprościej jest wtedy, gdy korzystamy z plików efektów (.fx) z DirectX. Wtedy można użyć funkcji D3DXCreateEffectFromFile
lub D3DXCreateEffectFromFile
, którym można przekazać wartości makr potrzebnych w danym przebiegu renderowania. Działa to tak, jakbyśmy użyli dyrektywy #define
bezpośrednio w kodzie efektu i podobnie do makr definiowanych w wierszu poleceń kompilacji w przypadku normalnych programów.
Otrzymany w ten sposób skompilowany shader należy oczywiście zachować, aby można było szybko przełączać między potrzebnymi wersjami w czasie renderowania. Wciąż jednak wymaga to ponownej kompilacji wszystkich używanych wersji shadera przy każdym uruchomieniu aplikacji – co jest marnotrawieniem czasu, jeżeli plik z kodem efektu się nie zmienia.
Można coś na to poradzić, stosując interfejs ID3DXEffectCompiler
zamiast zwykłego ID3DXEffect
. Ten pierwszy ma bowiem dodatkową, bardzo przydatną metodę CompileEffect
:
W wyniku jej użycia możemy dostać bufor (czyli w gruncie rzeczy kawałek pamięci wypełniony danymi binarnymi) zawierający efekt w postaci skompilowanej. Najważniejsze jest to, że w tej postaci możemy zapisać go do pliku (zwykle z rozszerzeniem .fxo) i później tylko szybko odczytać – bez czasochłonnej rekompilacji. W ten sposób można stworzyć mechanizm cache‘owania skompilowanych shaderów, który przyspieszy uruchamianie aplikacji.
Dzisiaj zastanowimy się nad refleksjami. Nie, nie jest to wcale masło maślane. Mechanizm refleksji (reflection – odbicie) jest zwany też introspekcją i polega na tym, iż działający program “wie” o swojej wewnętrznej strukturze. Prostą odmianą jest tutaj dynamiczna informacja o typie (RTTI), czyli możliwość określenia faktycznego typu obiektu znanego poprzez wskaźnik lub referencję.
W bardziej zaawansowanej wersji, obecnej na przykład w języku Java i na platformie .NET, refleksje są jednak czymś więcej. Stanowią faktyczne ‘odbicie’ struktury programu w postaci informacji dostępnych w czasie wykonania. Przy ich pomocy można na przykład uzyskać dokładne informacje o polach, metodach i właściwościach każdej klasy oraz jej miejscu w hierarchii dziedziczenia, nie mówiąc już o możliwości tworzenia jej instancji. Dostępność takich informacji umożliwia łatwe stworzenie modułu serializacji lub bardziej zaawansowanego odśmiecania pamięci, bazującego na przechodzeniu grafu odwołań między obiektami.
Ale C++ posiada tylko bardzo proste RTTI, które do takich celów jest daleko niewystarczające. Czy można jednak naprawić tę przypadłość? Jest na to kilka sposobów:
Gdybym aczkolwiek kiedyś cierpiał na dużą nadwyżkę wolnego czasu, to pewnie rozważyłbym implementację rozwiązania drugiego (lub jakiejś kombinacji rozwiązania drugiego i pierwszego, na przykład zlecającej rozwijanie makr programowi kompilującemu). Do tego czasu jednak C++ już dawno będzie posiadał wbudowany system refleksji ;)
Niektóre gry stają się legendarne… Dotyczy to w większości tych, które mają już swoje lata – jak choćby nieodżałowana pierwsza część Super Mario Bros.. Wielu przeszło ją nie raz i nie dwa razy (sam się do takich osób zaliczam :)), kiedy jeszcze królowała na ośmiobitowych konsolach.
Nie jest to oczywiście specjalne osiągnięcie, jako że jej zwykła wersja jest stosunkowo prosta. Jak przystało na grę nieśmiertelną, powstało jednak mnóstwo modów, hacków tudzież alternatywnych wersji.
Wśród nich jedna doczekała się całkiem sporej sławy jako najtrudniejszy wariant gry. A stało się tak z powodu tego oto filmu, na którym mierzy się z nią pewien gracz charakteryzujący się oryginalnym poczuciem humoru i – powiedzmy – dość mało powściągliwym sposobem wyrażania emocji ;) Zresztą tytuł mówi sam za siebie:
Super Mario Brothers – Frustration
Wszystkim fanom Mario i nie tylko, którzy jeszcze nie mieli okazji zobaczyć tej genialnej produkcji, niniejszym serdecznie ją polecam. Trzeba odkryć tajemnice technologii niewidzialnych bloczków ;]
Czy pamięta ktoś aplikację, która w Windows XP ma dość irytujący zwyczaj instalowania się, okazjonalnego włączania i działania przez cały czas w tle – nawet jeśli użytkownik nie za bardzo sobie tego życzy? Mam tu na myśli komunikator MSN Messenger. W Viście nie jest on już aczkolwiek składnikiem systemu i w razie potrzeby należy go osobno pobrać.
To właśnie zrobiłem za namową kolegi Asmodeusza i celem przyjrzenia się temu programowi, który obecnie zwie się zresztą Windows Live Messenger. Wnioski są takie, że w sumie jest to jeden z lepszych komunikatorów, jakich miałem okazję używać. Zwłaszcza dwie rzeczy zrobiły w nim na mnie pozytywne wrażenie. Pierwsza to rozbudowane możliwości zarządzania kontaktami i ustawiania różnych wzajemnych uprawnień, jak np. osób, które mogą nas widzieć niezależnie od naszego statusu. Drugą jest istniejąca obok zwykłego wysyłania plików funkcja ich współdzielenia, pozwalająca tworzyć katalogi dostępne dla nas i wybranych przez nas osób. Może nie jest to rozwiązanie na miarę rozbudowanego systemu kontroli wersji, ale kto wie – do prostych zastosowań może być wystarczające.
Wszystko byłoby dobrze, gdyby nie to, że w tym komunikatorze lista kontaktów zionie pustką :) W Polsce niestety tkwi on w tym zamkniętym, błędnym kole: (prawie) nikt go nie używa, bowiem… (prawie) nikt go nie używa. Raczej nie zanosi się więc, by mogło się to zmienić.
Z kolei znane skądinąd Gadu-Gadu “cierpi” na podobną przypadłość. Tyle że tutaj owo sprzężenie zwrotne jest dodatnie i duża liczba użytkowników jest świetnym podłożem dla dalszego wzrostu liczby użytkowników. Tak się nadal dzieje mimo wręcz przysłowiowej niestabilności serwerów, mechanizmu przesyłania plików który częściej nie działa niż działa oraz braku jakichkolwiek zaawansowanych funkcji, zwłaszcza związanych z zarządzaniem kontaktami.
Na Gadu-Gadu wszyscy lubią więc narzekać, lecz mało kto poszukuje alternatywy. Dlaczego? Ano właśnie dlatego, że… mało kto to robi :) “Logika” instynktu lemingów jest niestety nieubłagana.
A alternatywą mógłby być na przykład Skype, który nie przegrywa już na starcie z powodu małej liczby użytkowników. Przeciwnie, jest ich całkiem sporo, ale utarło się już, że program ten służy w zasadzie wyłącznie do rozmów głosowych. Otóż nie: ten sposób porozumiewania się oferuje dzisiaj każdy szanujący się komunikator, a Skype posiada też wszystkie inne funkcje, które są potrzebne w programie tego typu.
Lecz to oczywiście nie gwarantuje sukcesu. Wiele bardzo funkcjonalnych komunikatorów o sporych możliwościach nie przebiło się do szerszej świadomości, gdyż najwyraźniej najważniejszym kryterium decydującym o wyborze jest tutaj przyzwyczajenie. A te, jak wiadomo, bardzo trudno się zmienia.
Regedit zaprezentował dzisiaj w końcu demko prezentujące możliwości jego silnika, który – jak sam utrzymuje – niedawno ukończył. Wprawdzie ja nadal mam wątpliwości, czy wyrazy ‘silnik’ i ‘ukończony’ w ogóle powinny pojawiać się obok siebie, ale nie zmienia to faktu, że przynajmniej aktualnie istniejąca część jego engine‘u prezentuje się imponująco. Moje gratulacje!
Po więcej szczegółów zapraszam tutaj:
A ja w międzyczasie mogę dumać nad tym, ile to jeszcze miesięcy i lat zajmie mi dojście do podobnego poziomu ;)