June 2009

Uwaga! Informacje na tej stronie mają ponad 6 lat. Nadal je udostępniam, ale prawdopodobnie nie odzwierciedlają one mojej aktualnej wiedzy ani przekonań.

# Thoughts on Display Settings

Tue
23
Jun 2009

I've decided to make a demo for this year's Riverwash demoscene party. For that purpose recently I've prepared my framework and coded loading of display settings from either command line parameters, configuration file or my brand new dialog box:

Coding it reminded me of my thoughts about display settings from user's versus programmer's perspective. User is usually able to change screen resolution and sometimes also change refresh rate, turn vertical synchronization on/off, toggle between fullsreen and windowed mode, choose antialiasting, texture filtering quality and some general quality/performance parameters. On the other hand, programmer passes bunch of parameters to Direct3D as D3DDPRESENT_PARAMETERS structure and other arguments to functions CreateDevice and Reset. The question is how to map between these parameters?

Here are my current beliefs on this subject:

[+] Adapter: I just pass D3DADAPTER_DEFAULT constant. Sure it would be better to give a choice of an adapter (one can enumerate adapters using IDirect3D9 methods), but it's useful only on multi-monitor systems and not many games expose such setting.

[+] DeviceType: I always pass D3DDEVTYPE_HAL. Using software reference rasterizer D3DDEVTYPE_REF makes no sense, as it gives SPF instead of FPS :)

[+] BehaviorFlags: Now I always pass D3DCREATE_HARDWARE_VERTEXPROCESSING. Using software or mixed verex processing made sense only on old hardware, especially on old Intel laptop graphics chips, which had Pixel Shader 2.0 but no Vertex Shader at all.

[+] BackBufferWidth, BackBufferHeight: I give a choice of display modes available on default adapter with format hardcoded as constant (D3DFMT_X8R8G8B8). One can enumerate available display modes using IDirect3D9 methods. In windowed mode it could also be reasonable to be able to set any given resolution (Width and Height as text fields), as well as manually resize application's window.

[+] BackBufferFormat: I just use D3DFMT_A8R8G8B8. Choice between X8R8G8B8 and A8R8G8B8 just the matter of having additional fourth channel available (alpha), which is obviously not visible, but can be written, used in alpha blending and thus utilized to do some special effects (like masking intensity of some effect in screen space).

[+] BackBufferCount: I just give 0 here, which resolves to default value of 1 back buffer. I'm aware that using value 2 can change the way rendering is performed a bit.

[+] SwapEffect: I always use constant D3DSWAPEFFECT_DISCARD, as it is the fastest one. It says that entire content of the back buffer can be discarded after frame was presented and program have to render new frame from scratch (which is what we always do in game development).

[+] AutoDepthStencilFormat: Direct3D defines many of them, but for real all the D3D9 generation hardware supports only three: D3DFMT_D16, D24X8 and D24S8. So the choice is only based on the decision whether we need higher, 24-bit precision or stencil buffer.

[+] Flags: For the best performance possible I always give D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL and never give D3DPRESENTFLAG_LOCKABLE_BACKBUFFER.

[+] FullScreen_RefreshRateInHz: Nowadays, when many (most?) people have LCD displays, standard refresh rate is 60 Hz and maybe 75 Hz. In the CRT era setting good refresh rate was crucial for playing comfort and thus it was very annoying when a game didn't expose setting of refresh rate, but used default 60 Hz instead. I believe refresh rates should be enumerated and given as a choice next to the resolution.

[+] PresentationInterval: This is the value the "VSync" setting is converted to. It looks like D3DPRESENT_INTERVAL_DEFAULT behaves as VSync turned on (FPS <= RefreshRate) and D3DPRESENT_INTERVAL_IMMEDIATE means VSync off (FPS as high as possible), but once during my experiments I've observed that flag D3DPRESENT_INTERVAL_ONE behaves slightly different than D3DPRESENT_INTERVAL_DEFAULT (I can't remember the details now).

I know I would sound more "professional" if I considered all other constant values available and their possible uses, but I don't care :) My point here was to simplify the problem to be able to map these technical parameters to the display settings exposed to the user. Multisampling is separate subject so I don't cover it here.

Comments | #demoscene #directx #rendering Share

# New Web Browsers: Safari 4 and Opera Unite

Sun
21
Jun 2009

Two new web browser applications have been released recently: Opera Unite and Safari 4. Of course they are both free. Here is my quick review.

Starting with the second one, I must admit I've never used Safari before. I generally dislike Apple corporation, but today I read news about new Safari 4 and decided to try it on my laptop.

My general impression is rather good. The browser's look and feel is quite standard comparing to other popular programs of this kind (Internet Explorer, Firefox, Opera). The same applies to keyboard shortcuts and set of features. All websites I tried work OK in Safari. To make long story short - Safari is yet another web browser, not bad but also not so special.

There is one (not so) small issue though. For all of you who complain about performance and memory consumption of Firefox: try Safari or just look at the screenshot below and you will change your mind :) I just entered one website (www.onet.pl) on both browsers.

Now let me say few words about Opera Unite. I tried Opera before and my impressions were very positive (although I still use Firefox). Personally I think Opera is a very good web browser - it launches and runs very fast, has lots of features and its GUI is nice. This time I just wanted to test brand new functionality introduced to Opera Unite - a personal web server.

To set up your own server, you just need to click on a command in Opera menu. Then you have to create an account in Opera system (standard question about your login + password + email). According to current trends in Internet applications (like Skype or Hamachi), there is no or minimum technical configuration required. Opera proposes use of UPnP (to forward ports through router) and automatically sets up something like dynamic DNS in operaunite.com domain.

Not only is the server setup far from what you have to do to install and configure Apache server, but sharing files is so easy too. You just need to point to a directory on your hard disk and it automatically gets shared, so people can explore directories and download files if they know correct URL (for example, the URL for my test was http://reg-laptop.reg01.operaunite.com/file_sharing/). I think I don't have to add that there is no need to code or setup any CMS script to make it work. You just put your files and a nice website for browsing them is generated automatically.

There are also some other "services" available. Photo Sharing works just like File Sharing, but looks like a gallery, where user can see image thumbnails instead of list of files. Fridge allows you and other people to leave sticky notes on your virtual fridge :) The Lounge is a chat service. Finally, Web Server is a normal server where you can put your own website starting from index.html. It looks like Opera Unite supports only HTML, without any PHP, MySQL or other stuff like this.

Opera Unite really impressed me. I've never seen anything like this before and now I think it will cause kind of a small revolution in the Web. Internet have always been server-oriented and transferring/sharing files between regular users always have been an issue. Of course Opera Unite is not going to replace traditional website hosting services (most of home computers do not work 24/7), but it can greatly support exchanging files between people.

Comments | #web #software Share

# ASCII Art in Pixel Shader

Thu
18
Jun 2009

Today I'm going to show completely ugly and useless effect :) I have always been fascinated with ASCII art, so I'm glad I am now able to visualize it on GPU. Here is the final effect:

And here is how I've made it. First, I took a 3D scene with some untextured boxes.

Now I do pixelate effect to have my image looking like each 8 x 8 pixel group have same color. Optimally I should render whole scene into 8 x 8 times smaller render target and rewrite it with POINT filtering, but currently I'm just doing some processing during rewriting this image from render target texture to the back buffer. That processing is simply rounding texture coordinate down to a multiply of 8 texels:

// in float2 TexCoord : TEXCOORD0
// float2 g_PixelateParam = float2(BackBufSizeX / 8, BackBufSizeY / 8)
TexCoord = floor(TexCoord * g_PixelateParam) / g_PixelateParam;
float4 Color = tex2D(RenderTargetSampler, TexCoord);

Then for each pixel I calculate its luminance using weighted average of RGB values:

float Grayscale = dot(Color.rgb, float3(0.299, 0.587, 0.114));

And finally I'm doing a lookup into specially prepared volume texture. XY coordinates are taken from texel position in screen space, while Z (depth) coordinate is just the pixel luminance.

float2 TexXY = (Pos-float2(0.5,0.5))/g_VolumeLookupTextureSize.xy;
float  TexZ = Grayscale;
float4 VolSample = tex3D(VolumeLookupSampler, float3(TexXY.x, TexXY.y, TexZ));
Color.rgb = VolSample.rgb;

The texture is prepared so that its subsequent slices contain ASCII characters: from empty black image, through dark gray dot on black background, dark gray comma, colon, until white hash on light gray background and finally blank white image. Here you can download this texture (I've made it using GIMP and DirectX Texture Tool): Atari Font.dds.

To make it pixel-perfect, I had to bias XY texture coordinate by (-0.5, -0.5) texels, as well as turn off texture filtering:

Dev->SetSamplerState(3, D3DSAMP_MINFILTER, D3DTEXF_POINT);
Dev->SetSamplerState(3, D3DSAMP_MAGFILTER, D3DTEXF_POINT);

It also turned off smooth transitioning between slices in volume texture (it means ASCII characters are not blended together), It's what I actually wanted to do, but by the way I realized that we cannot switch filtering for separate texture coordinate axes (e.g. only UV or only W), just like we do with addressing modes (D3DSAMP_ADDRESSU and so on). It could be useful sometimes... Anyway, we can achieve that with pixel shader.

Comments | #rendering Share

# Switching to English

Tue
16
Jun 2009

I've decided to switch my website to English. I'm aware I'm not a master of English, so I can make some horrible language mistakes. Please forgive me that and also don't be afraid to tell me about them. You can post your comments in both English and Polish, as my website encoding is still Polish ISO-8859-2.

So why did I do it? I think game programming is a narrow and exotic subject, so if I share some knowledge here, more people will be able to benefit from it if I post it in English. Besides, most of programming stuff I read is in English, so it's actually even easier for me to write about programming in English than trying to translate all these technical terms to Polish, where there's often no single elegant translation. Many of other Polish programmers also blog in English, like Yarpen or SirMike, just to name a few. It's not that I don't care about my Polish friends. I still love you guys :) I just believe that all the programmers who can understand the stuff I post here can also read in English, as it's very important skill for every programmer.

All my older blog entries, descriptions of my productions and many other stuff will be still in Polish, as I'm not going to translate all these 677 records. I hope it won't bother anyone - all in all Internet is full of websites in exotic languages :)

Comments | #homepage Share

# forum.gamedev.pl z innej strony

Sun
14
Jun 2009

W ostatnim czasie bardzo się zmieniłem. Może spowodował to wiek, mała ilość wolnego czasu, może jeszcze coś innego... W każdym razie udzielanie się na forum.gamedev.pl już nie sprawia mi tyle frajdy, co dawniej. Nie będę ogłaszał żadnego oficjalnego "odejścia z Warsztatu", bo nadal pasjonuję się programowaniem gier, a w Sieci nadal chętnie odpowiadam na ciekawe, techniczne, konkretne pytania. Jednak ogólnie na nasze forum patrzę teraz trochę z innej strony i dostrzegam ogólne schematy, które mnie nużą. Wg mnie większość pytań na forum można podzielić na takie typy:

[+] "Nie działa mi", czyli problem z utworzeniem projektu, błąd kompilatora albo linkera, ewentualnie problem z instalacją jakiejś biblioteki. Najczęściej problem polega na tym, że pytający nie zna podstaw obsługi Visual C++ albo języka C++ (np. nie umie wyłączyć Unicode albo Precompiled Headers w opcjach projektu). Nie mam nic przeciwko takim pytaniom. Zdaję sobie sprawę, że to, co dla zaawansowanych jest banalne, to dla początkujących stanowi nie lada przeszkodę - a przecież każdemu należy się szacunek i pomoc. Kwestia tylko, że te pytania wracają bardzo często jak bumerang, a odpowiedź musiałaby być zawsze taka sama.

[+] "Który wybrać" - język programowania, IDE, silnik, książkę do nauki, kartę graficzną, uczelnię lub cokolwiek. Problem z tego typu pytaniami jest taki, że nie ma jednej dobrej odpowiedzi. Oczywiście, są opcje lepsze i gorsze, ale każdy z odpowiadających ma swoje preferencje i dlatego zwykle nie mam ochoty czytać kilku stron odpowiedzi w stylu "ja polecam to", "a ja polecam tamto".

[+] Typowe problemy, przez które każdy musi przejść w początkach nauki programowania gier. Nie ma w nich nic złego, ale osobom z dłuższym stażem na forum po prostu nie chce się odpowiadać na to samo pytanie po raz setny. Najczęściej chodzi m.in. o: wydajne sprawdzanie kolizji (rozwiązanie: techniki podziału przestrzeni), działanie gry w stałym tempie (rozwiązanie: mnożenie prędkości razy delta_t), konwersja między liczbą a łańcuchem.

[+] "Porozmawiajmy o...", czyli ktoś rzuca temat (nazwa jakiejś nowinki, gry, technologii, czegokolwiek) tak jakby chciał powiedzieć: "niech każdy z was napisze teraz pod spodem, co o tym myśli". Dalej zgodnie z tym życzeniem ciągną się odpowiedzi w stylu "ja myślę że tak", "a ja myślę że tak", "a wcale nie bo tak" i nic z tego w sumie nie wynika.

[+] "Jak wydać grę" i inne tematy biznesowe: Są tacy, którzy chcieliby widzieć więcej takich dyskusji zamiast tylko o programowaniu, ale ja widzę z takimi wątkami co najmniej kilka problemów. Pierwszy: pytania często zadają młodzi pasjonaci, którzy nie skończyli i nie mają szansy w najbliższym czasie skończyć pisania swojej gry, a martwią się na zapas. Drugi: odpowiadającymi są często "profesjonaliści", którzy w swoich wiadomościach nie piszą żadnych konkretów i chcą tylko pokazać, jak bardzo są obeznani z tym biznesem. Trzeci: do takiej dyskusji często włączają się jacyś anonimowi panowie (nieraz specjalnie w tym celu zarejestrowani), którzy wygłaszając swoje mądrości nie szczędzą krytyki innym osobom czy nawet całym firmom. Przy takich tematach nigdy nie wiadomo, kto jest kim i po co napisał to co napisał, czy to nie "pijarowiec" z konkurencyjnej firmy.

[+] Wracająca co jakiś czas, epicka, ogólnowarsztatowa dyskusja jednego z dwóch rodzajów: albo nad "losami" naszego community, gdzie przeważa narzekanie tak jakbyśmy przeżywali wielki kryzys (chociaż tak naprawdę jest bardzo dobrze - w końcu ciągniemy już ponad 9 lat!!!), albo propozycja zebrania się i wspólnego napisania jednej, wielkiej gry (co jak wynika z wielokrotnego doświadczenia, nie ma szansy się udać).

Na zakończenie coś śmiesznego: Prawo Godwina (znane też m.in. jako "argumentum ad hitlerum"), które brzmi:

Podczas przeciągającej się dyskusji w Internecie prawdopodobieństwo przyrównania czegoś lub kogoś do nazizmu bądź Hitlera dąży do 1.

Brzmi nieprawdopodobnie, bo jakże można przejść od programowania do Hitlera? A jednak! Całkiem niedawno był sobie wątek Zarobki programisty. Dyskusja toczyła się i toczyła, aż około 15 strony zeszło na temat obozów koncentracyjnych i wątek trzeba było zamknąć. Cóż... Internet ma swoje prawa, a praw przyrody się nie oszuka :)

Comments | #humor #warsztat #web Share

# Dithering i inny postprocessing

Thu
11
Jun 2009

Dziś dalej bawiłem się w pisanie efektów postprocessingu. Szczególnie zainteresował mnie Dithering. Ta technika była stosowana do polepszania jakości obrazów w czasach, kiedy komputery dysponowały ograniczoną liczbą dostępnych kolorów. W szerszym kontekście Dithering oznacza celowe wprowadzanie szumów do sygnału celem zniwelowania nieprzyjemnego efektu powstającego w wyniku kwantyzacji do pewnej, małej liczby możliwych wartości (np. tylko kilka bitów na składowe RGB piksela czy próbkę dźwięku).

Dzisiejszy DirectX już nawet nie obsługuje palet, ale pomyślałem sobie, że napisanie takiego efektu renderowanego w czasie rzeczywistym za pomocą shaderów to będzie ciekawa część poznawania zagadnień związanych z tematem efektów pełnoekranowych i Non-Photorealistic Rendering.

Zasada działania takiego efektu jest stosunkowo prosta. Jeśli w kodzie shadera HLSL mamy dany kolor piksela Color.rgb, to możemy zmniejszyć precyzję każdego kanału do tylko 2, 3, 4 itd... możliwych wartości (g_DownsamplingFactor) za pomocą takiej operacji:

float Bias = 0.5;
Color.rgb = floor(Color.rgb * g_DownsamplingFactor + Bias) /
  g_DownsamplingFactor;

To 0.5 służy do zaokrąglenia części ułamkowej, zamiast jej obcięcia. Jeśli teraz to przesunięcie 0.5 zastąpimy przesunięciem losowym w zakresie 0..1 (bez wartości skrajnych), to otrzymamy Dithering. Oto efekt:

 

 

 

Comments | #graphics #rendering #tools Share

# Czcionki z komputera Atari

Tue
09
Jun 2009

Współcześnie "Atari" kojarzy się z wydawcą gier, ale kiedyś pod tą marką produkowane były komputery - w czasach, zanim jeszcze pecet podbił świat. W sobotę byłem na imprezie demoscenowej poświęconej miłośnikom klasycznych platform (przede wszystkim, jak się okazało, 8-bitowych Atari). Na tym spotkaniu m.in. wykłady miał TDC. Dowiedziałem się z nich bardzo dużo o budowie i możliwościach sprzętu tamtej generacji (w tym układu graficznego), ówczesnym oprogramowaniu i rynku gier. Okazuje się, że Wolfenstein i Doom wcale nie były pierwsze i że bardzo dużo działo się już w czasach, kiedy mnie jeszcze nie było na tym świecie :)

Przy okazji trafiłem na polskie strony poświęcone Atari - atari.area i Atari Online, a na nich znalazłem kolekcję czcionek z tej platformy: [1], [2]. W przypływie dziwnej ochoty (zapewne spowodowanej niewyspaniem) postanowiłem dopisać wsparcie dla nich do swojego domowego projektu (pisanego oczywiście na PC i w DirectX).

Specyfikacji formatu pliku FNT nigdzie nie znalazłem, ale udało mi się go rozgryźć samemu. To z resztą nie było trudne, jeśli wiadomo, że taki plik ma 1024 bajty, a zawarta w nim czcionka to 128 znaków bitmapowych po 8x8 pikseli monochromatycznych. W końcu 128*8*8 = 8192 b = 1024 B :) Toteż napisałem samemu specyfikację tego formatu: Atari Font FNT File Format.txt, a czcionki z wyżej wspomnianej strony (razem ze screenami) pozwoliłem sobie spakować i udostępnić jako jedno archiwum, żeby łatwiej było ściągać - Atari_Fonts.zip. Przykładowa czcionka (jedna z 335) o nazwie "Atari" wygląda tak:

A efekt mojego kodowania prezentuje się tak (niezły oldschool :D)

Comments | #events #gui #rendering #gallery #demoscene Share

# MFC i Smart PropertyGrid

Sat
06
Jun 2009

Używam w pracy MFC i powiem wam, że wbrew temu co się mówi (i co wcześniej powtarzałem za innymi), to wcale nie jest taka zła biblioteka. Ta dostępna w płatnych wersjach Visual C++ biblioteka do GUI to tak naprawdę cienka, obiektowa nakładka na WinAPI. Tak więc ma swoje klasy odpowiadające m.in. różnym kontrolkom interfejsu, obiektom GDI itp., ale z zestawów flag bitowych czy też zasobów z zaprojektowanymi graficznie okienkami korzysta już z tych samych, co czyste WinAPI. Nie oferuje zbyt wiele ponad to, co API systemowe, ale trochę uprzyjemnia pracę. Jeśli ktoś zna dobrze WinAPI, to nie ma kłopotów z opanowaniem MFC ani powodów do narzekań, chyba że co najwyżej na to, że biblioteka jest tym czym jest i niczym więcej.

Szukałem wczoraj rozwiązania kwestii kontrolki Property Grid dla MFC i znalazłem bibliotekę Smart PropertyGrid.MFC firmy Visualhint. Jest świetna - ładna, potężna, rozszerzalna, a dzięki dobrze zaprojektowanemu interfejsowi opartemu na wielu klasach i koncepcji iteratorów, także wygodna w użyciu. Twórcy udostępnili ją całkowicie za darmo, bo teraz rozwijają i sprzedają wersję tej kontrolki dla .NET (choć przecież platforma .NET ma taką kontrolkę w standardzie).

Smart PropertyGrid.MFC

Comments | #c++ #gui #libraries #winapi #visual studio Share

# Non-Photorealistic Rendering

Thu
04
Jun 2009

Szukając informacji na temat cieniowania kreskówkowego (Cell Shading) stwierdziłem, że temat renderowania obrazów stylizowanych, nie dążących do fotorealizmu, jest badany od wielu lat i stanowi obszerną dziedzinę. Dwa linkowiska zbierające sporo publikacji na ten temat to: Stylized Depiction in Computer Graphics, Non-Photorealistic Rendering.

Mnie szczególnie wpadł w oko artykuł A Non-Photorealistic Lighting Model For Automatic Technical Illustration (Amy Gooch, Bruce Gooch, Peter Shirley, Elaine Cohen, SIGGRAPH 1998). Autorzy przedstawili bardzo prostą, ale ciekawie pomyślaną technikę cieniowania stawiającą na czytelność ilustracji technicznych. Żeby ją zastosować, trzeba pomieszczać zwykłe oświetlenie światłem kierunkowym (Diffuse + Specular, brak cienia) z przejściem od kolorów ciepłych w stronę światła (żółty) do zimnych w stronę przeciwną (niebieski) i do tego dodać wykrywanie krawędzi.

Napisałem sobie coś takiego i wyrenderowałem śrubkę. Model znalazłem na tej stronie.

Comments | #rendering Share

# Zabawy z GIMP-em #1 - Bloom

Tue
02
Jun 2009

Wiadomo, że programista to nie grafik - talentu artystycznego mieć nie musi. Ale warto umieć obsługiwać jakiś program graficzny, bo jego wykorzystanie bywa przydatne i całkiem ciekawe. Na przykład za pomocą GIMP-a możemy "statycznie" uzyskiwać efekty, które na co dzień kodujemy w czasie rzeczywistym, na GPU i za pomocą wszelkich zaawansowanych technik koderskich.

Jako przykład weźmy "słynny" efekt Bloom. Do jego wykonania posłuży darmowy GIMP. Mamy zdjęcie (Warszawa, centrum handlowe Złote Tarasy):

Duplikujemy jego warstwę (Layer / Duplicate Layer). Tą warstwę wyższą przekształcamy za pomocą krzywej (Color / Curves) tak, żeby wybrać tylko jasne obszary:

Potem tą warstwę mocno rozmywamy za pomocą Filter / Gaussian Blur:

Wreszcie przestawiamy tryb warstwy (Mode w panelu Layers) na addytywny (Addition) i Bloom gotowy - wszystko świeci! :D

Comments | #graphics #tools #rendering Share

[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2024