14_sdl_basics.txt, 15_color.txt.

This commit is contained in:
Relintai 2021-04-05 16:54:14 +02:00
parent b4909b5204
commit 3b83756125
3 changed files with 201 additions and 0 deletions

115
14_sdl_basics.txt Normal file
View File

@ -0,0 +1,115 @@
Először nézzük meg, hogy hogy is működik az SDL2.
--------------------------------------------------------------------------------------------------------
Fontos tudni, hogy ez egy C könyvtár, ami úgy van megcisnálva, hogy működjön c++-al is!
Azaz: Csak structok vannak, és ezekbe nincsenek függvények!
Szóval sok olyan függvénnyel fogunk találkozni:
SDL_Renderer* r = SDL_CreateRenderer(...)
SDL_GetRendererOutputSize(r, ...)
SDL_CreateTexture(r, ...)
etc...
Úgy érdemes erre gondolni, mitnha a this* paramétert, ami c++-ban eléhető minden osztály
tagfüggvényben, itt az első paraméterként adjuk be.
--------------------------------------------------------------------------------------------------------
Az SDL egy relatíve szimpla könytár, gyakolratilag nem sokkal több, mint sok platform
fölötti absztrakciós réteg.
Pl.: Minden platformon máshogy kell ablakot létrehozni, ablakra rajzolni, hangokat lejátszani,
bementete kezelni, fájlokat megynitni, stb. Az SDL gyakorlatilag csak ezeket csinálja meg nekünk,
egy egyesített interface-en keresztül.
Elérhető benne egy software-es, és hardware-es renderer. A hardware-es rajzoló az jelenleg az OpenGL,
vagy a Vulkan lehet.
A különbség közöttük:
A software-es renderer a CPUt használva állítgatja be / számolgatja ki egy ablak pixeleinek értékét,
míg a hardware-es renderer a GPUt használva csinálja ugyanezt.
Fontos tudni, hogy a software-es renderert jóval egyszerűbb használni / először beállítani,
mint a hardware-est. (Nem annyival nehezebb, de sok plussz kódot, és magyarázatot igényel,
inkább a szokatlansága miatt.) Ugyanis a gpu úgy működik, hogy mindent az ő általa egyszerűen
értelmezhető formátumba kell konvertálni, illetve külön manage-elni kell az egyéb dolgokat,
pl. a képeket fel kell neki tölteni.
Viszont! A GPUkban több száz mag található, míg a cpukban általában csak 4-5!
Természetesen a hátránya a GPUs magoknak, hogy nagyon szimplák!
De a lényeg az, hogy a softwares rajzolóknak az általános problémája, ha sok pixelt kell feldolgozniuk
nagyon gyorsan. Jóval kisebb az ilyen kimeneti teljesítményük. Hogy mennyi pixelt képesek feldolgozni,
az természetesen sokmindentől függ, én sajnos nem tudok erre pontos számokat. A lényeg, hogy tudjatok róla.
Ettől függetlenül azért a softwares renderereknek van előnye, sőt képesek elég jó dolgokra is!
(Pl Quake, DOOM, Duke Nukem 3D, WolfEinstein 3D, etc... mind softwares renderereket használtak! Érdemes utánanézni,
hogy hogy működtek, vannak már róluk videók is a youtube-on.)
Egyenlőre csak a software-est fogjuk használni.
(Lehet, hogy majd egyszer a hardware-es renderert is belerakom. Majd kiderül.)
Szóval: először a cél az, hogy az egyszerűbb felhasználás érdekében építsünk osztályokat az SDL2
C API-ja köré.
--------------------------------------------------------------------------------------------------------
==== Egy kis bevezető: ====
Elég csak az SDL.h-t includeolni a projektben! Így:
#include <SDL.h>
---- Rajzolás: ----
A legfőbb osztályok:
SDL_Window: //SDL_render.h ban lehet megnézni a függvényeket
Az ablak adatainak mutatója. Minden platformon más lessz kicsit mögötte.
Amikor létrehozatjuk, akkor hozatja létre az sdl maga az ablakot az operációs rendszerrel.
Az ablak módosításához van rá szükség. Pl át lehet nevezni, meg ilyenek.
SDL_Renderer: //SDL_render.h ban lehet megnézni a függvényeket
Az ablak mögötti rajzoló oszály mutatója. Lehet softwares, és hardwares is.
Rajzoláshoz van rá szükség.
Fontos tudni, hogy a softwares, és a hardwares renderert máshogy kell használni, szóval
sajnos nem triviális váltani közöttük!
SDL_Surface: //SDL_surface.h, SDL_image.h ban lehet megnézni a függvényeket
Egy képnek az adatait tartalmazza. Sokféle belső formátumot képes kezelni.
SDL_Texture: //SDL_render.h ban lehet megnézni a függvényeket
Ugyanúgy, mint egy SDL_Surface, egy kép adatait tartalmazza, viszont ez a softwares rajzoláshoz
optimalizált formában.
---- Bemenet: ----
SDL_Event: //SDL_event.h ban lehet megnézni a függvényeket
Egy struct, ami egy bemenet adatait tartalmazza.
Nagyon sok adattagja van, bármilyen eventet le tud tárolni.
A bemenetek guis appoknál úgy működnek, hogy amikor a felhasználó valamit csinál,
pl megmozdítja az egeret, vagy lenyom egy billentyűt, akkor az eltárolódik, egy queue-ban,
és nekünk (a számunkra megfelelő helyen a programunkban) ki kell kéregetnünk ezeket az eventeket,
és fel kell őket dolgoznunk.
Azaz, ha megmozdítjuk az egeret, akkor:
SDL_event type mezője SDL_MOUSEMOTION lesz, és az adatokat el fogjuk tuni érni a motion mezőben.
---- Egyéb: ----
Audio, fájlok, etc, ugyan így működnek, nézzetek körbe a headerekben, illetve az SDL wiki jén, ha
használni szeretnétek őket, nem fogunk rájuk kitérni.
(Legalábbis egyenlőre biztosan nem, talán majd egyszer.)

81
15_color.txt Normal file
View File

@ -0,0 +1,81 @@
Először, írjunk egy szín osztályt:
Megj.: Csak a legszükségesebb dolgokat raktam bele, nyugodtan egészítsétek ki, ha akarjátok!
|--------------------------------------------------------------------------|
| class Color |
|--------------------------------------------------------------------------|
| + uint32_t to_key() const; | <- lejjebb (hasznos lesz)
| + void from_key(const uint32_t key); | <- lejjebb
| |
| + Color(); |
| + Color(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a = 255); |
| + Color(const uint32_t key); |
| + virtual ~Color(); |
| |
| + uint8_t r; | <- #include <inttypes.h> ban van, 8 bites előjel nélküli int -> 0-256 os értéket tud felvenni
| + uint8_t g; |
| + uint8_t b; |
| + uint8_t a; |
|--------------------------------------------------------------------------|
uint32_t Color::to_key() const {
uint32_t val = 0;
//<< = left shift int típusoknál -> azaz az intek bitjeit eltolja eggyel balra:
//pl.: 001010101 ből lesz: 010101010, aztán 101010100, aztán 010101000 etc
//az r az uint8_t, azaz egy 8 bites int (unsigned byte típus pl java/c#-ban)
//tehát alakítsuk át 32 bites uint-é: static_cast<uint32_t>(r)
//Ez az új c++-os castolás, lehetne így is: (uint32_t) r
//De, nem ajánlják már, mert ez 4-5 ilyen static_cast, dynamic_cast etc függvényt
//próbál végig, megadott sorrendben, és csak kiírtam a megfelelőt expliciten.
//static_cast<uint32_t>(r) << 24: (8db 0) (8db 0) (8db 0) (r száma) Ez lessz: (r száma) (8db 0) (8db 0) (8db 0)
//static_cast<uint32_t>(g) << 24: (8db 0) (8db 0) (8db 0) (g száma) Ez lessz: (8db 0) (g száma) (8db 0) (8db 0)
//static_cast<uint32_t>(b) << 24: (8db 0) (8db 0) (8db 0) (b száma) Ez lessz: (8db 0) (8db 0) (b száma) (8db 0)
//static_cast<uint32_t>(a) << 24: (8db 0) (8db 0) (8db 0) (a száma) Ez lessz: (8db 0) (8db 0) (8db 0) (a száma)
//| a bináris vagy -> a számok birtjeit össze bináris vagyolja -> azaz ahol valaho 1 van, ott az eredmény be egy lesz: 00100 | 00010 -> 00110
//|= -> bináris vagy egyenlő
val |= static_cast<uint32_t>(r) << 24;
val |= static_cast<uint32_t>(g) << 16;
val |= static_cast<uint32_t>(b) << 8;
val |= static_cast<uint32_t>(a) << 0;
//azaz a végeredmény:
//1 uint32t, aminek a bitjei: (r száma) (g száma) (b száma) (a száma)
return val;
}
void Color::from_key(const uint32_t key) {
//A to_key függvény megfordítása.
//& itt a bináris és.
//azok a bitek lesznek 1ek, amik mindkét operandusba 1-ek: 001010 & 111110 -> 001010
//A 16-os számrendszerbeli számokat 0x<valami> formában lehet megadni.
//Azért használtam 16os számrendszerbeli számokat, mert itt sokkal szemléletesebbek.
//Ugyanis-> 0xF = 1111
//Azaz minden F 4db 1es bitet jelöl.
//Így már biztosan látszik, hogy mit csinálunk
//key & 0xFF000000 kiszedjük a legelől levő 8 bitet (Minden más bit biztosan 0 lesz.), etc
r = (key & 0xFF000000) >> 24;
g = (key & 0x00FF0000) >> 16;
b = (key & 0x0000FF00) >> 8;
a = (key & 0x000000FF) >> 0;
//>> az itt a right shift, ugyan az mint a left shift, csak itt a biteket jobbra mozgatjuk
//Nyilván, egyéb módon is meg lehet csinálni ezt a függvényt.
//pl csak right shiftelgetni, és castolni uint8_t-vé az eredményt, etc.
//Azért cisnáltam így, mert szerintem ezt a módszert a leghasznosabb látni hosszú távon.
//Pl. ugyan így lehet hálózati csomagokat méretre optimalizálni.
}

View File

@ -10,3 +10,8 @@ vagy
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
Megj.: WolfEinstein 3D rendererjét úgy hívják, hogy raycaster. Nem sok kód szükséges hozzá, pár száz sor csak
Vannak róla tutorialok a zoutube-on, még talán beimplementálni is érdemes.